Пример #1
0
    def _impl(self):
        self._parseTemplate()
        # build read data output mux

        st_t = HEnum('st_t', ['idle', "writeAck", 'readDelay', 'rdData'])
        ipif = self.bus
        addr = ipif.bus2ip_addr
        ipif.ip2bus_error(0)
        addrVld = ipif.bus2ip_cs

        isInMyAddrSpace = self.isInMyAddrRange(addr)

        st = FsmBuilder(self, st_t)\
        .Trans(st_t.idle,
            (addrVld & isInMyAddrSpace & ipif.bus2ip_rnw, st_t.rdData),
            (addrVld & isInMyAddrSpace & ~ipif.bus2ip_rnw, st_t.writeAck)
        ).Trans(st_t.writeAck,
            st_t.idle
        ).Trans(st_t.readDelay,
            st_t.rdData
        ).Trans(st_t.rdData,
            st_t.idle
        ).stateReg

        wAck = st._eq(st_t.writeAck)
        ipif.ip2bus_rdack(st._eq(st_t.rdData))
        ipif.ip2bus_wrack(wAck)
        ADDR_STEP = self._getAddrStep()
        dataToBus = ipif.ip2bus_data(None)
        for (_, _), t in reversed(self._bramPortMapped):
            # map addr for bram ports
            _addr = t.bitAddr // ADDR_STEP
            _isMyAddr = inRange(addr, _addr, t.bitAddrEnd // ADDR_STEP)
            port = self.getPort(t)

            self.propagateAddr(addr, ADDR_STEP, port.addr,
                               port.dout._dtype.bit_length(), t)

            port.en(_isMyAddr & ipif.bus2ip_cs)
            port.we(_isMyAddr & wAck)

            dataToBus = If(_isMyAddr,
                           ipif.ip2bus_data(port.dout)).Else(dataToBus)

            port.din(ipif.bus2ip_data)

        self.connect_directly_mapped_write(ipif.bus2ip_addr, ipif.bus2ip_data,
                                           ~ipif.bus2ip_rnw & wAck)
        self.connect_directly_mapped_read(ipif.bus2ip_addr, ipif.ip2bus_data,
                                          dataToBus)
Пример #2
0
    def _impl(self):
        stT = HEnum("st_t", ["a", "b", "aAndB"])

        a = self.a
        b = self.b
        out = self.dout

        st = FsmBuilder(self, stT)\
        .Trans(stT.a,
            (a & b, stT.aAndB),
            (b, stT.b)
        ).Trans(stT.b,
            (a & b, stT.aAndB),
            (a, stT.a)
        ).Trans(stT.aAndB,
            (a & ~b, stT.a),
            (~a & b, stT.b),
        ).stateReg

        Switch(st)\
        .Case(stT.a,
              out(1)
        ).Case(stT.b,
              out(2)
        ).Case(stT.aAndB,
              out(3)
        )
Пример #3
0
    def mainFsm(self, dataRegR_vld):
        ipif = self.m
        axi = self.s
        st_t = HEnum("st_t", [
            "idle", "write", "write_wait_data", "write_ack", "read", "read_ack"
        ])

        st = FsmBuilder(self, st_t).Trans(
            st_t.idle,
            # ready for new request
            (axi.ar.valid, st_t.read),
            (axi.aw.valid, st_t.write_wait_data),
        ).Trans(
            st_t.write_wait_data,
            # has address but needs data from axi
            (axi.w.valid, st_t.write),
        ).Trans(
            st_t.write,
            # has address and data from axi and writing to ipif
            (ipif.ip2bus_wrack & axi.b.ready, st_t.idle),
            (ipif.ip2bus_wrack, st_t.write_ack),
        ).Trans(
            st_t.write_ack,
            # data was writen waiting for write response to axi,
            (axi.b.ready, st_t.idle)).Trans(
                st_t.read,
                # has address, reading from ipif
                ((ipif.ip2bus_rdack | dataRegR_vld) & axi.r.ready, st_t.idle),
                (ipif.ip2bus_rdack, st_t.read_ack),
            ).Trans(
                st_t.read_ack,
                # read from ipif complete, waiting for axi to accept data
                (axi.r.ready, st_t.idle)).stateReg

        return st
Пример #4
0
    def _impl(self):
        # :note: stT member names are colliding with port names and thus
        #     they will be renamed in HDL
        stT = HEnum("st_t", ["a", "b", "aAndB"])

        a = self.a
        b = self.b
        out = self.dout

        st = FsmBuilder(self, stT)\
        .Trans(stT.a,
            (a & b, stT.aAndB),
            (b, stT.b)
        ).Trans(stT.b,
            (a & b, stT.aAndB),
            (a, stT.a)
        ).Trans(stT.aAndB,
            (a & ~b, stT.a),
            (~a & b, stT.b),
        ).stateReg

        Switch(st)\
        .Case(stT.a,
              out(1)
        ).Case(stT.b,
              out(2)
        ).Case(stT.aAndB,
              out(3)
        )
Пример #5
0
    def baseAddrLogic(self, nextBlockTransition_in):
        """
        Logic for downloading address of next block

        :param nextBlockTransition_in: signal which means that baseIndex should be changed to nextBaseIndex
            if nextBaseAddrReady is not high this signal has no effect (= regular handshake)
        :return: (baseIndex, nextBaseIndex, nextBaseReady is ready and nextBlockTransition_in can be used)
        """
        r = self._reg
        rIn = self.rDatapump.r
        rReq = self.rDatapump.req

        addr_index_t = Bits(self.ADDR_WIDTH - self.ALIGN_BITS)
        baseIndex = r("baseIndex_backup", addr_index_t)
        nextBaseIndex = r("nextBaseIndex", addr_index_t)
        t = HEnum("nextBaseFsm_t", ["uninitialized",
                                   "required",
                                   "pending",
                                   "prepared"])
        isNextBaseAddr = rIn.valid & rIn.id._eq(self.ID)
        nextBaseFsm = FsmBuilder(self, t, "baseAddrLogic_fsm")\
        .Trans(t.uninitialized,
            (self.baseAddr.dout.vld, t.required)
        ).Trans(t.required,
            (rReq.rd, t.pending)
        ).Trans(t.pending,
            (isNextBaseAddr, t.prepared)
        ).Trans(t.prepared,
            (nextBlockTransition_in, t.required)
        ).stateReg

        If(self.baseAddr.dout.vld,
           baseIndex(self.addrToIndex(self.baseAddr.dout.data)),
        ).Elif(nextBlockTransition_in,
           baseIndex(nextBaseIndex)
        )
        self.baseAddr.din(self.indexToAddr(baseIndex))

        If(isNextBaseAddr,
           nextBaseIndex(self.addrToIndex(fitTo(rIn.data, rReq.addr)))
        )
        rIn.ready(1)

        self.rReqHandler(baseIndex, nextBaseFsm._eq(t.required))

        nextBaseReady = nextBaseFsm._eq(t.prepared)
        return baseIndex, nextBaseIndex, nextBaseReady 
Пример #6
0
    def writePart(self):
        sig = self._sig
        reg = self._reg

        wSt_t = HEnum('wSt_t', ['wrIdle', 'wrData', 'wrResp'])
        aw = self.bus.aw
        w = self.bus.w
        b = self.bus.b

        # write fsm
        wSt = FsmBuilder(self, wSt_t, "wSt")\
            .Trans(wSt_t.wrIdle,
                (aw.valid, wSt_t.wrData)
            ).Trans(wSt_t.wrData,
                (w.valid, wSt_t.wrResp)
            ).Trans(wSt_t.wrResp,
                (b.ready, wSt_t.wrIdle)
           ).stateReg

        awAddr = reg('awAddr', aw.addr._dtype)
        w_hs = sig('w_hs')

        awRd = wSt._eq(wSt_t.wrIdle)
        aw.ready(awRd)
        aw_hs = awRd & aw.valid

        wRd = wSt._eq(wSt_t.wrData)
        w.ready(wRd)

        w_hs(w.valid & wRd)

        # save aw addr
        If(aw_hs,
            awAddr(aw.addr)
        ).Else(
            awAddr(awAddr)
        )
        self.connect_directly_mapped_write(awAddr, w.data, w_hs)
        for (_, _), t in self._bramPortMapped:
            # en, we handled in readPart
            din = self.getPort(t).din
            din(w.data, fit=True)

        self.writeRespPart(awAddr, wSt._eq(wSt_t.wrResp))

        return awAddr, w_hs
Пример #7
0
    def baseAddrLogic(self, nextBlockTransition_in):
        """
        Logic for downloading address of next block

        :param nextBlockTransition_in: signal which means that baseIndex
               should be changed to nextBaseIndex if nextBaseAddrReady
               is not high this signal has no effect (= regular handshake)
        :return: (baseIndex, nextBaseIndex, nextBaseReady is ready
                 and nextBlockTransition_in can be used)
        """
        r = self._reg
        rIn = self.rDatapump.r
        rReq = self.rDatapump.req

        addr_index_t = Bits(self.ADDR_WIDTH - self.ALIGN_BITS)
        baseIndex = r("baseIndex_backup", addr_index_t)
        nextBaseIndex = r("nextBaseIndex", addr_index_t)
        t = HEnum("nextBaseFsm_t",
                  ["uninitialized", "required", "pending", "prepared"])
        isNextBaseAddr = rIn.valid & rIn.id._eq(self.ID)
        nextBaseFsm = FsmBuilder(self, t, "baseAddrLogic_fsm")\
        .Trans(t.uninitialized,
            (self.baseAddr.dout.vld, t.required)
        ).Trans(t.required,
            (rReq.rd, t.pending)
        ).Trans(t.pending,
            (isNextBaseAddr, t.prepared)
        ).Trans(t.prepared,
            (nextBlockTransition_in, t.required)
        ).stateReg

        If(
            self.baseAddr.dout.vld,
            baseIndex(self.addrToIndex(self.baseAddr.dout.data)),
        ).Elif(nextBlockTransition_in, baseIndex(nextBaseIndex))
        self.baseAddr.din(self.indexToAddr(baseIndex))

        If(isNextBaseAddr,
           nextBaseIndex(self.addrToIndex(fitTo(rIn.data, rReq.addr))))
        rIn.ready(1)

        self.rReqHandler(baseIndex, nextBaseFsm._eq(t.required))

        nextBaseReady = nextBaseFsm._eq(t.prepared)
        return baseIndex, nextBaseIndex, nextBaseReady
Пример #8
0
    def _io_core(
            self, data_in: Hd44780CmdIntf,
            cmd_timer_rst,
            lcd_clk_en: RtlSignal,
            delay_cmd_half_done: RtlSignal,
            delay_cmd_done: RtlSignal,
            delay_cmd_long_done: RtlSignal):
        st_t = HEnum("st_t", [
            "init_delay_after_powerup",
            "idle",
            "write",  # cmd/data
        ])
        is_long_cmd = self._reg("is_long_cmd")
        st = FsmBuilder(self, st_t, "st")\
            .Trans(st_t.init_delay_after_powerup, (delay_cmd_long_done, st_t.idle))\
            .Trans(st_t.idle, (data_in.vld, st_t.write))\
            .Trans(st_t.write, ((is_long_cmd & delay_cmd_long_done) |
                                (~is_long_cmd & delay_cmd_done), st_t.idle))\
            .stateReg
        cmd_timer_rst(st._eq(st_t.idle))

        data_in.rd(st._eq(st_t.write) & ((delay_cmd_done & ~is_long_cmd) |
                                         (delay_cmd_long_done & is_long_cmd)))

        data_out = self.dataOut
        data_out.d(data_in.d)
        data_out.rw(data_in.rw)
        data_out.rs(data_in.rs)

        en_in_first_half_period = self._reg("en_in_first_half_period", def_val=1)
        If(st._eq(st_t.idle),
            is_long_cmd(data_in.long_wait),
            en_in_first_half_period(1),
        ).Elif(en_in_first_half_period & delay_cmd_half_done,
            en_in_first_half_period(0),
        )

        en_delay = self._reg("en_delay", def_val=0)
        If(lcd_clk_en,
           en_delay((st != st_t.idle) & en_in_first_half_period)
        )
        data_out.en(en_delay)
Пример #9
0
    def _impl(self):
        self._parseTemplate()
        # build read data output mux

        st_t = HEnum('st_t', ['idle', 'readDelay', 'rdData'])
        bus = self.bus
        addr = bus.address
        addrVld = bus.read | bus.write

        st = FsmBuilder(self, st_t)\
            .Trans(st_t.idle,
                (addrVld & bus.read, st_t.rdData),
                (addrVld & bus.write, st_t.idle)
            ).Trans(st_t.readDelay,
                st_t.rdData
            ).Trans(st_t.rdData,
                st_t.idle
            ).stateReg

        wAck = True
        wr = bus.write & wAck
        isInAddrRange = (self.isInMyAddrRange(bus.address))

        If(isInAddrRange,
            bus.response(RESP_OKAY)
        ).Else(
            bus.response(RESP_SLAVEERROR)
        )
        bus.waitRequest(bus.read & ~st._eq(st_t.rdData))
        bus.readDataValid(st._eq(st_t.rdData))
        bus.writeResponseValid(wr)

        ADDR_STEP = self._getAddrStep()
        dataToBus = bus.readData(None)
        for (_, _), t in reversed(self._bramPortMapped):
            # map addr for bram ports
            _addr = t.bitAddr // ADDR_STEP
            _isMyAddr = inRange(addr, _addr, t.bitAddrEnd // ADDR_STEP)
            wasMyAddr = self._reg("wasMyAddr")
            If(st._eq(st_t.idle),
                wasMyAddr(_isMyAddr)
            )
            port = self.getPort(t)

            self.propagateAddr(addr, ADDR_STEP, port.addr,
                               port.dout._dtype.bit_length(), t)

            port.en(_isMyAddr & addrVld)
            port.we(_isMyAddr & wr)

            dataToBus = If(wasMyAddr & st._eq(st_t.rdData),
                           bus.readData(port.dout)
                        ).Else(
                            dataToBus
                        )

            port.din(bus.writeData)

        self.connect_directly_mapped_write(addr, bus.writeData, wr)
        self.connect_directly_mapped_read(bus.address, bus.readData, dataToBus)
Пример #10
0
    def _impl(self):
        self._parseTemplate()
        # build read data output mux

        def isMyAddr(addrSig, addr, end):
            return (addrSig >= addr) & (addrSig < end)

        st_t = HEnum('st_t', ['idle', "writeAck", 'readDelay', 'rdData'])
        ipif = self.bus
        addr = ipif.bus2ip_addr
        ipif.ip2bus_error(0)
        addrVld = ipif.bus2ip_cs

        isInMyAddrSpace = self.isInMyAddrRange(addr)

        st = FsmBuilder(self, st_t)\
        .Trans(st_t.idle,
            (addrVld & isInMyAddrSpace & ipif.bus2ip_rnw, st_t.rdData),
            (addrVld & isInMyAddrSpace & ~ipif.bus2ip_rnw, st_t.writeAck)
        ).Trans(st_t.writeAck,
            st_t.idle
        ).Trans(st_t.readDelay,
            st_t.rdData
        ).Trans(st_t.rdData,
            st_t.idle
        ).stateReg

        wAck = st._eq(st_t.writeAck)
        ipif.ip2bus_rdack(st._eq(st_t.rdData))
        ipif.ip2bus_wrack(wAck)
        ADDR_STEP = self._getAddrStep()
        dataToBus = ipif.ip2bus_data(None)
        for t in reversed(self._bramPortMapped):
            # map addr for bram ports
            _addr = t.bitAddr // ADDR_STEP
            _isMyAddr = isMyAddr(addr, _addr, t.bitAddrEnd // ADDR_STEP)
            port = self.getPort(t)

            self.propagateAddr(addr, ADDR_STEP, port.addr, port.dout._dtype.bit_length(), t)

            port.en(_isMyAddr & ipif.bus2ip_cs)
            port.we(_isMyAddr & wAck)

            dataToBus = If(_isMyAddr,
                ipif.ip2bus_data(port.dout)
            ).Else(
                dataToBus
            )

            port.din(ipif.bus2ip_data)

        for t in self._directlyMapped:
            _addr = t.bitAddr // ADDR_STEP
            port = self.getPort(t)

            port.dout.vld(addr._eq(_addr) & ~ipif.bus2ip_rnw & wAck)
            port.dout.data(ipif.bus2ip_data)

        _isInBramFlags = []
        Switch(ipif.bus2ip_addr)\
        .addCases(
                [(t.bitAddr // ADDR_STEP, ipif.ip2bus_data(self.getPort(t).din))
                 for t in self._directlyMapped]
        ).Default(
            dataToBus
        )
Пример #11
0
    def _impl(self):
        propagateClkRstn(self)

        # stash is storage for item which is going to be swapped with actual
        stash_t = HStruct(
            (Bits(self.KEY_WIDTH), "key"),
            (Bits(self.DATA_WIDTH), "data"),
            (Bits(log2ceil(self.MAX_REINSERT + 1)), "reinsert_cntr"),
            (BIT, "item_vld"),
            (ORIGIN_TYPE, "origin_op"),
        )
        stash = self._reg("stash", stash_t, def_val={"origin_op": ORIGIN_TYPE.DELETE})

        cleanAck = self._sig("cleanAck")
        cleanAddr, cleanLast = self.clean_addr_iterator(cleanAck)
        lookupResRead = self._sig("lookupResRead")
        (lookupResVld,
         insertFinal,
         lookupFoundOH,
         insertTargetOH) = self.tables_lookupRes_resolver(lookupResRead)
        lookupAck = StreamNode(slaves=[t.lookup for t in self.tables]).ack()
        insertAck = StreamNode(slaves=[t.insert for t in self.tables]).ack()

        lookup_in_progress = self.lookup_trans_cntr()
        lookup_not_in_progress = rename_signal(self,
            lookup_in_progress._eq(0) & (stash.origin_op != ORIGIN_TYPE.LOOKUP),
            "lookup_not_in_progress")
        isDelete = stash.origin_op._eq(ORIGIN_TYPE.DELETE)
        isInsert = stash.origin_op._eq(ORIGIN_TYPE.INSERT)
        # lookup is not blocking and does not use FSM bellow
        # this FSM handles only lookup for insert/delete
        fsm_t = HEnum("insertFsm_t", ["idle", "cleaning",
                                      "lookup", "lookupResWaitRd",
                                      "lookupResAck"])
        state = FsmBuilder(self, fsm_t, "insertFsm")\
            .Trans(fsm_t.idle,
                   # wait before lookup_in_progress reaches 0
                   # (new transactions should not be allowed if command has vld)
                   (lookup_not_in_progress & self.clean.vld, fsm_t.cleaning),
                   # before each insert suitable place has to be searched first
                   (lookup_not_in_progress & (self.insert.vld | self.delete.vld), fsm_t.lookup)
            ).Trans(fsm_t.cleaning,
                # walk all items and clean it's item_vlds
                (insertAck & cleanLast, fsm_t.idle),
            ).Trans(fsm_t.lookup,
                # insert timeout
                (stash.reinsert_cntr._eq(0) & isInsert & self.insertRes.rd, fsm_t.idle),
                # search and resolve in which table item
                # should be stored
                (((stash.reinsert_cntr != 0) | ~isInsert) & lookupAck, fsm_t.lookupResWaitRd)
            ).Trans(fsm_t.lookupResWaitRd,
                # process result of lookup and
                (lookupResVld, fsm_t.lookupResAck)
            ).Trans(fsm_t.lookupResAck,
                # process lookupRes, if we are going to insert on place where
                # valid item is, this item has to be stored to stash
                (isDelete, fsm_t.idle),
                # insert into specified table
                (insertAck & insertFinal & (isDelete | self.insertRes.rd), fsm_t.idle),
                # insert and swap with some valid item from the table
                # which we need to store somewhere as well
                (insertAck & ~insertFinal, fsm_t.lookup)
            ).stateReg

        cleanAck(insertAck & state._eq(fsm_t.cleaning))
        lookupResRead(state._eq(fsm_t.lookupResWaitRd))
        lookupResNext = rename_signal(
            self,
            (state._eq(fsm_t.idle) & self.lookupRes.rd) |
            (state._eq(fsm_t.lookupResAck) & (state.next != fsm_t.lookupResAck)),
            "lookupResNext")
        # synchronize all lookupRes from all tables
        StreamNode(masters=[t.lookupRes for t in self.tables]).sync(lookupResNext)

        self.stash_load(
            state._eq(fsm_t.idle),
            lookupResNext,
            insertTargetOH,
            stash,
            lookup_not_in_progress,
            lookup_in_progress != self.MAX_LOOKUP_OVERLAP - 1)
        insertIndex = self.insert_addr_select(insertTargetOH, state, cleanAddr)
        self.insertRes_driver(state, stash, insertAck, insertFinal, isDelete)
        self.tables_insert_driver(state, insertTargetOH, insertIndex, stash)
        self.lookupRes_driver(state, lookupFoundOH)

        lookup_en =rename_signal(
            self,
            (state._eq(fsm_t.lookup) & ((stash.reinsert_cntr != 0) | isDelete)) |
            (state._eq(fsm_t.idle) & stash.origin_op._eq(ORIGIN_TYPE.LOOKUP)),
            "lookup_en"
        )
        self.tables_lookup_driver(state, stash.key, lookup_en)
Пример #12
0
    def _impl(self):
        cmd = self.cntrl.cmd
        cmd_ack = self.cntrl.rd

        stT = HEnum("stT", [
            "idle", "start_0", "start_1", "start_2", "start_3", "start_4",
            "stop_0", "stop_1", "stop_2", "stop_3", "rd_0", "rd_1", "rd_2",
            "rd_3", "wr_0", "wr_1", "wr_2", "wr_3"
        ])

        fsm = FsmBuilder(self, stT)
        st = fsm.stateReg

        # check SDA status (multi-master arbitration)
        sda_chk = self._reg("sda_chk", def_val=0)
        scl_t = self._reg("scl_t", def_val=0)
        sda_t = self._reg("sda_t", def_val=0)

        scl = self.filter("scl", self.i2c.scl.i)
        sda = self.filter("sda", self.i2c.sda.i)

        _, stopCond, scl_sync = self.detectStartAndStop(scl, sda, scl_t)
        stateClkEn = self.stateClkGen(scl_sync, scl_t, scl)
        al = self.arbitrationLostDriver(st, sda, sda_chk, sda_t, stopCond,
                                        stateClkEn)

        def stateSequence(sequneceName, stateCnt):
            for i in range(stateCnt):
                stateFrom = getattr(stT, f"{sequneceName}_{i:d}")
                if i == stateCnt - 1:
                    stateTo = stT.idle
                else:
                    _i = i + 1
                    stateTo = getattr(stT, f"{sequneceName}_{_i:d}")

                fsm.Trans(stateFrom, (al, stT.idle), stateTo)

        fsm.Trans(
            stT.idle,
            (al, stT.idle),
            (cmd._eq(NOP), stT.idle),
            (cmd._eq(START), stT.start_0),
            (cmd._eq(STOP), stT.stop_0),
            (cmd._eq(WRITE), stT.wr_0),
            (cmd._eq(READ), stT.rd_0),
        )
        stateSequence("start", 5)
        stateSequence("stop", 4)
        stateSequence("rd", 4)
        stateSequence("wr", 4)

        If(
            al,
            cmd_ack(0),
            sda_t(0),
            scl_t(0),
            sda_chk(0),
        ).Else(
            If(
                In(st, [
                    stT.start_1, stT.start_2, stT.start_3, stT.stop_1,
                    stT.stop_2, stT.stop_3, stT.rd_1, stT.rd_2, stT.wr_1,
                    stT.wr_2
                ]), scl_t(0)).Elif(
                    In(st, [
                        stT.start_4, stT.stop_0, stT.rd_0, stT.rd_3, stT.wr_0,
                        stT.wr_3
                    ]), scl_t(1)),
            If(
                In(st, [
                    stT.start_0, stT.start_1, stT.stop_3, stT.rd_0, stT.rd_1,
                    stT.rd_2, stT.rd_3
                ]), sda_t(0)).Elif(
                    In(st, [
                        stT.start_2, stT.start_3, stT.start_4, stT.stop_0,
                        stT.stop_1, stT.stop_2
                    ]), sda_t(1)).Elif(
                        In(st, [stT.wr_0, stT.wr_1, stT.wr_2, stT.wr_3]),
                        sda_t(~self.cntrl.din)),
            # cmd ack at the end of state sequence
            cmd_ack(In(st, [stT.start_4, stT.stop_3, stT.rd_3, stT.wr_3])))

        self.i2c.scl.o(0)
        self.i2c.sda.o(0)
        self.i2c.scl.t(scl_t)
        self.i2c.sda.t(sda_t)
Пример #13
0
    def _impl(self):
        propagateClkRstn(self)
        lookupRes = self.lookupRes
        tables = self.tables

        # stash is storage for item which is going to be swapped with actual
        stash_t = HStruct(
            (Bits(self.KEY_WIDTH), "key"),
            (Bits(self.DATA_WIDTH), "data"),
            (BIT, "vldFlag")
        )
        stash = self._reg("stash", stash_t)
        lookupOrigin = self._reg("lookupOrigin", Bits(2))

        cleanAck = self._sig("cleanAck")
        cleanAddr, cleanLast = self.cleanUpAddrIterator(cleanAck)
        lookupResRead = self._sig("lookupResRead")
        lookupResNext = self._sig("lookupResNext")
        (lookupResAck,
         insertFinal,
         insertFound,
         targetOH) = self.lookupResOfTablesDriver(lookupResRead,
                                                  lookupResNext)
        lookupAck = StreamNode(slaves=map(lambda t: t.lookup, tables)).ack()
        insertAck = StreamNode(slaves=map(lambda t: t.insert, tables)).ack()

        fsm_t = HEnum("insertFsm_t", ["idle", "cleaning",
                                      "lookup", "lookupResWaitRd",
                                      "lookupResAck"])

        isExternLookup = lookupOrigin._eq(ORIGIN_TYPE.LOOKUP)
        state = FsmBuilder(self, fsm_t, "insertFsm")\
            .Trans(fsm_t.idle,
                   (self.clean.vld, fsm_t.cleaning),
                   # before each insert suitable place has to be searched first
                   (self.insert.vld | self.lookup.vld | 
                    self.delete.vld, fsm_t.lookup)
                   ).Trans(fsm_t.cleaning,
                           # walk all items and clean it's vldFlags
                           (cleanLast, fsm_t.idle)
                           ).Trans(fsm_t.lookup,
                                   # search and resolve in which table item
                                   # should be stored
                                   (lookupAck, fsm_t.lookupResWaitRd)
                                   ).Trans(fsm_t.lookupResWaitRd,
                                           # process result of lookup and
                                           # write data stash to tables if
                                           # required
                                           (lookupResAck, fsm_t.lookupResAck)
                                           ).Trans(fsm_t.lookupResAck,
                                                   # process lookupRes, if we are going to insert on place where
                                                   # valid item is, it has to
                                                   # be stored
                                                   (lookupOrigin._eq(
                                                       ORIGIN_TYPE.DELETE), fsm_t.idle),
                                                   (isExternLookup & 
                                                    lookupRes.rd, fsm_t.idle),
                                                   # insert into specified
                                                   # table
                                                   (~isExternLookup & insertAck & 
                                                    insertFinal, fsm_t.idle),
                                                   (~isExternLookup & insertAck & 
                                                    ~insertFinal, fsm_t.lookup)
                                                   ).stateReg

        cleanAck(StreamNode(slaves=[t.insert for t in tables]).ack() & 
                 state._eq(fsm_t.cleaning))
        lookupResRead(state._eq(fsm_t.lookupResWaitRd))
        lookupResNext(And(state._eq(fsm_t.lookupResAck),
                          Or(lookupOrigin != ORIGIN_TYPE.LOOKUP, lookupRes.rd)))

        isIdle = state._eq(fsm_t.idle)
        self.stashLoad(isIdle, stash, lookupOrigin)
        insertIndex = self.insertAddrSelect(targetOH, state, cleanAddr)
        self.insetOfTablesDriver(
            state, targetOH, insertIndex, stash, isExternLookup)
        self.lookupResDriver(state, lookupOrigin, lookupAck, insertFound)
        self.lookupOfTablesDriver(state, stash.key)
Пример #14
0
    def _impl(self):
        # timers and other registers
        CLK_HALF_PERIOD_DIV = ceil(self.clk.FREQ / (self.MDIO_FREQ * 2))
        mdio_clk = self._reg("mdio_clk", def_val=0)
        r_data_vld = self._reg("r_data_vld", def_val=0)
        req = self.req
        clk_half_period_en = ClkBuilder(self, self.clk).timer(
            ("clk_half_period_en", CLK_HALF_PERIOD_DIV))
        If(
            clk_half_period_en,
            mdio_clk(~mdio_clk),
        )
        mdio_clk_rising = clk_half_period_en & ~mdio_clk
        mdio_clk_falling = clk_half_period_en & mdio_clk
        idle = self._sig("idle")
        preamble_last, addr_block_last, turnarround_last_en, data_last =\
            self._packet_sequence_timer(
                mdio_clk_rising, mdio_clk_falling, ~idle)
        is_rx = self._reg("is_rx", def_val=0)

        # protocol FSM
        st_t = HEnum("st_t", ["idle", "pre", "addr_block", "ta", "data"])
        st = FsmBuilder(self, st_t)\
            .Trans(st_t.idle, (req.vld & ~r_data_vld, st_t.pre))\
            .Trans(st_t.pre, (preamble_last, st_t.addr_block))\
            .Trans(st_t.addr_block, (addr_block_last, st_t.ta))\
            .Trans(st_t.ta, (turnarround_last_en & (
                                (is_rx & mdio_clk_falling)
                                | (~is_rx & mdio_clk_rising)), st_t.data))\
            .Trans(st_t.data, (data_last, st_t.idle)).stateReg

        idle(st._eq(st_t.idle))
        req.rd(idle & ~r_data_vld)
        If(idle, is_rx(req.opcode._eq(Mdio.OP.READ)))

        # TX logic
        md = self.md
        TX_W = md.ST_W + md.OP_W + md.PA_W + md.RA_W + md.TA_W + md.D_W
        tx_reg = self._reg("tx_reg", Bits(TX_W))
        If(
            idle & req.vld,
            tx_reg(
                Concat(
                    Mdio.ST, req.opcode, req.addr.phy, req.addr.reg, Mdio.TA,
                    req.wdata))).Elif(
                        mdio_clk_falling
                        & In(st,
                             [st_t.addr_block, st_t.data, st_t.ta, st_t.data]),
                        tx_reg(tx_reg << 1))
        md.c(mdio_clk)

        # because MDIO uses open-drain, this means that if t=0 the value of the signal is 1
        md.io.o(0)
        tx_bit = tx_reg[tx_reg._dtype.bit_length() - 1]
        md.io.t(~idle & ~tx_bit & (st._eq(st_t.addr_block)
                                   | (In(st, [st_t.data, st_t.ta]) & ~is_rx)))

        # RX logic
        rx_reg = self._reg("rx_reg", Bits(md.D_W))
        If(
            st._eq(st_t.data) & is_rx & mdio_clk_rising,
            shift_in_msb_first(rx_reg, self.md.io.i))

        If(idle & self.rdata.rd, r_data_vld(0)).Elif(addr_block_last,
                                                     r_data_vld(is_rx))
        self.rdata.vld(idle & r_data_vld)
        self.rdata.data(rx_reg)
Пример #15
0
    def itemUploadLogic(self, baseIndex, nextBaseIndex, nextBaseReady, nextBlockTransition_out):
        r, s = self._reg, self._sig
        f = self.dataFifo
        w = self.wDatapump

        BURST_LEN = self.BUFFER_CAPACITY // 2
        bufferHasData = s("bufferHasData")
        bufferHasData(f.size > (BURST_LEN - 1))
        # we are counting base next addr as item as well
        addr_index_t = Bits(self.ADDR_WIDTH - self.ALIGN_BITS)
        baseIndex = r("baseIndex", addr_index_t)

        dataCntr_t = Bits(log2ceil(BURST_LEN + 1), signed=False)
        dataCntr = r("dataCntr", dataCntr_t, defVal=0)  # counter of uploading data
        reqLen_backup = r("reqLen_backup", w.req.len._dtype, defVal=0)

        gotWriteAck = w.ack.vld & w.ack.data._eq(self.ID)
        queueHasSpace, lenByPtrs = self.queuePtrLogic(fitTo(reqLen_backup, self.wrPtr.din) + 1, gotWriteAck)

        timeout = s("timeout")
        fsm_t = HEnum("itemUploadingFsm_t", ["idle",
                                            "reqPending",
                                            "dataPending_prepare",
                                            "dataPending_send",
                                            "waitForAck"])
        fsm = FsmBuilder(self, fsm_t, "itemUploadLogic_fsm")\
        .Trans(fsm_t.idle,
            (timeout | (bufferHasData & queueHasSpace), fsm_t.reqPending)

        ).Trans(fsm_t.reqPending,
            (w.req.rd, fsm_t.dataPending_prepare)

        ).Trans(fsm_t.dataPending_prepare,
            fsm_t.dataPending_send
        ).Trans(fsm_t.dataPending_send,
            ((~nextBlockTransition_out | nextBaseReady) & dataCntr._eq(0), fsm_t.waitForAck)
        ).Trans(fsm_t.waitForAck,
            (gotWriteAck, fsm_t.idle)    
        ).stateReg

        timeout(self.timeoutHandler(fsm != fsm_t.idle,
                                    (f.size != 0) & queueHasSpace))

        inBlock_t = Bits(log2ceil(self.ITEMS_IN_BLOCK + 1))
        inBlockRemain = r("inBlockRemain_reg", inBlock_t, defVal=self.ITEMS_IN_BLOCK)

        wReqEn = fsm._eq(fsm_t.reqPending)
        reqLen = self.wReqDriver(wReqEn, baseIndex, lenByPtrs, inBlockRemain)

        If(wReqEn & w.req.rd,
           reqLen_backup(reqLen)
        )

        dataMoveEn = fsm._eq(fsm_t.dataPending_send)
        prepareEn = fsm._eq(fsm_t.dataPending_prepare)
        self.mvDataToW(prepareEn, dataMoveEn, reqLen_backup,
                               inBlockRemain, nextBlockTransition_out, dataCntr)

        If(self.baseAddr.dout.vld,
           baseIndex(self.addrToIndex(self.baseAddr.dout.data)),
        ).Elif(prepareEn,
           baseIndex(baseIndex + fitTo(reqLen_backup, baseIndex) + 1)    
        ).Elif(nextBlockTransition_out,
           baseIndex(nextBaseIndex)
        )

        w.ack.rd(fsm._eq(fsm_t.waitForAck))
Пример #16
0
    def _impl(self):
        ALIGN_BITS = log2ceil(self.DATA_WIDTH // 8 - 1)
        TIMEOUT_MAX = self.TIMEOUT - 1
        ITEMS = self.ITEMS
        buff = self.buff
        reqAck = self.wDatapump.ack
        req = self.wDatapump.req
        w = self.wDatapump.w

        propagateClkRstn(self)

        sizeOfitems = self._reg("sizeOfItems", Bits(
            buff.size._dtype.bit_length()))

        # aligned base addr
        baseAddr = self._reg("baseAddrReg", Bits(self.ADDR_WIDTH - ALIGN_BITS))
        If(self.baseAddr.dout.vld,
           baseAddr(self.baseAddr.dout.data[:ALIGN_BITS])
        )
        self.baseAddr.din(Concat(baseAddr, Bits(ALIGN_BITS).from_py(0)))

        # offset in buffer and its complement
        offset_t = Bits(log2ceil(ITEMS + 1), signed=False)
        offset = self._reg("offset", offset_t, def_val=0)
        remaining = self._reg("remaining", Bits(
            log2ceil(ITEMS + 1), signed=False), def_val=ITEMS)
        self.buff_remain(remaining, fit=True)

        addrTmp = self._sig("baseAddrTmp", baseAddr._dtype)
        addrTmp(baseAddr + fitTo(offset, baseAddr))

        # req values logic
        req.id(self.ID)
        req.addr(Concat(addrTmp, Bits(ALIGN_BITS).from_py(0)))
        req.rem(0)

        sizeTmp = self._sig("sizeTmp", buff.size._dtype)

        assert (req.len._dtype.bit_length()
                == buff.size._dtype.bit_length() - 1), (
            req.len._dtype.bit_length(), buff.size._dtype.bit_length())

        buffSizeAsLen = self._sig("buffSizeAsLen", buff.size._dtype)
        buffSizeAsLen(buff.size - 1)
        buffSize_tmp = self._sig("buffSize_tmp", remaining._dtype)
        buffSize_tmp(buff.size, fit=True)

        endOfLenBlock = (remaining - 1) < buffSize_tmp

        remainingAsLen = self._sig("remainingAsLen", remaining._dtype)
        remainingAsLen(remaining - 1)

        If(endOfLenBlock,
            req.len(remainingAsLen, fit=True),
            sizeTmp(remaining, fit=True)
        ).Else(
            req.len(buffSizeAsLen, fit=True),
            sizeTmp(buff.size)
        )

        lastWordCntr = self._reg("lastWordCntr", buff.size._dtype, 0)
        w_last = lastWordCntr._eq(1)
        w_ack = w.ready & buff.dataOut.vld

        # timeout logic
        timeoutCntr = self._reg("timeoutCntr", Bits(log2ceil(self.TIMEOUT), False),
                                def_val=TIMEOUT_MAX)
        # buffer is full or timeout
        beginReq = buff.size._eq(self.BUFF_DEPTH) | timeoutCntr._eq(0)
        reqAckHasCome = self._sig("reqAckHasCome")
        reqAckHasCome(reqAck.vld & reqAck.data._eq(self.ID))
        st = FsmBuilder(self, stT)\
            .Trans(stT.waitOnInput,
                (beginReq & req.rd, stT.waitOnDataTx)
            ).Trans(stT.waitOnDataTx,
                    (w_last & w_ack, stT.waitOnAck)
            ).Trans(stT.waitOnAck,
                    (reqAckHasCome, stT.waitOnInput)
            ).stateReg

        If(st._eq(stT.waitOnInput) & beginReq,  # timeout is counting only when there is pending data
            # start new request
            req.vld(1),
            If(req.rd,
                If(endOfLenBlock,
                   offset(0),
                   remaining(ITEMS)
                ).Else(
                    offset(offset + fitTo(buff.size, offset)),
                    remaining(remaining - fitTo(buff.size, remaining))
                ),
                sizeOfitems(sizeTmp),
                timeoutCntr(TIMEOUT_MAX)
            )
        ).Else(
            req.vld(0),
            If(buff.dataOut.vld & st._eq(stT.waitOnInput) & (timeoutCntr != 0),
               timeoutCntr(timeoutCntr - 1)
            )
        )

        reqAck.rd(st._eq(stT.waitOnAck))

        self.uploadedCntrHandler(st, reqAckHasCome, sizeOfitems)

        # it does not matter when lastWordCntr is changing when there is no
        # request
        startSendingData = st._eq(stT.waitOnInput) & beginReq & req.rd
        If(startSendingData,
            lastWordCntr(sizeTmp)
        ).Elif((lastWordCntr != 0) & w_ack,
            lastWordCntr(lastWordCntr - 1)
        )

        buff.dataIn(self.items)

        w.data(buff.dataOut.data, fit=True)

        StreamNode(
            masters=[buff.dataOut],
            slaves=[w]
        ).sync(st._eq(stT.waitOnDataTx))
        w.strb(mask(w.strb._dtype.bit_length()))
        w.last(w_last)
Пример #17
0
    def itemUploadLogic(self, baseIndex, nextBaseIndex, nextBaseReady,
                        nextBlockTransition_out):
        r, s = self._reg, self._sig
        f = self.dataFifo
        w = self.wDatapump

        BURST_LEN = self.BUFFER_CAPACITY // 2
        bufferHasData = s("bufferHasData")
        bufferHasData(f.size > (BURST_LEN - 1))
        # we are counting base next addr as item as well
        addr_index_t = Bits(self.ADDR_WIDTH - self.ALIGN_BITS)
        baseIndex = r("baseIndex", addr_index_t)

        dataCntr_t = Bits(log2ceil(BURST_LEN + 1), signed=False)
        # counter of uploading data
        dataCntr = r("dataCntr", dataCntr_t, def_val=0)
        reqLen_backup = r("reqLen_backup", w.req.len._dtype, def_val=0)

        gotWriteAck = w.ack.vld & w.ack.data._eq(self.ID)
        queueHasSpace, lenByPtrs = self.queuePtrLogic(
            fitTo(reqLen_backup, self.wrPtr.din) + 1, gotWriteAck)

        timeout = s("timeout")
        fsm_t = HEnum("itemUploadingFsm_t", [
            "idle", "reqPending", "dataPending_prepare", "dataPending_send",
            "waitForAck"
        ])
        fsm = FsmBuilder(self, fsm_t, "itemUploadLogic_fsm")\
        .Trans(fsm_t.idle,
            (timeout | (bufferHasData & queueHasSpace), fsm_t.reqPending)

        ).Trans(fsm_t.reqPending,
            (w.req.rd, fsm_t.dataPending_prepare)

        ).Trans(fsm_t.dataPending_prepare,
            fsm_t.dataPending_send
        ).Trans(fsm_t.dataPending_send,
            ((~nextBlockTransition_out | nextBaseReady) & dataCntr._eq(0), fsm_t.waitForAck)
        ).Trans(fsm_t.waitForAck,
            (gotWriteAck, fsm_t.idle)
        ).stateReg

        timeout(
            self.timeoutHandler(fsm != fsm_t.idle,
                                (f.size != 0) & queueHasSpace))

        inBlock_t = Bits(log2ceil(self.ITEMS_IN_BLOCK + 1))
        inBlockRemain = r("inBlockRemain_reg",
                          inBlock_t,
                          def_val=self.ITEMS_IN_BLOCK)

        wReqEn = fsm._eq(fsm_t.reqPending)
        reqLen = self.wReqDriver(wReqEn, baseIndex, lenByPtrs, inBlockRemain)

        If(wReqEn & w.req.rd, reqLen_backup(reqLen))

        dataMoveEn = fsm._eq(fsm_t.dataPending_send)
        prepareEn = fsm._eq(fsm_t.dataPending_prepare)
        self.mvDataToW(prepareEn, dataMoveEn, reqLen_backup, inBlockRemain,
                       nextBlockTransition_out, dataCntr)

        If(
            self.baseAddr.dout.vld,
            baseIndex(self.addrToIndex(self.baseAddr.dout.data)),
        ).Elif(prepareEn,
               baseIndex(baseIndex + fitTo(reqLen_backup, baseIndex) +
                         1)).Elif(nextBlockTransition_out,
                                  baseIndex(nextBaseIndex))

        w.ack.rd(fsm._eq(fsm_t.waitForAck))
Пример #18
0
    def _impl(self):
        self._parseTemplate()

        # build read data output mux

        def isMyAddr(addrSig, addr, end):
            return (addrSig >= addr) & (addrSig < end)

        st_t = HEnum('st_t', ['idle', "writeAck", 'readDelay', 'rdData'])
        ipif = self.bus
        addr = ipif.bus2ip_addr
        ipif.ip2bus_error(0)
        addrVld = ipif.bus2ip_cs

        isInMyAddrSpace = self.isInMyAddrRange(addr)

        st = FsmBuilder(self, st_t)\
        .Trans(st_t.idle,
            (addrVld & isInMyAddrSpace & ipif.bus2ip_rnw, st_t.rdData),
            (addrVld & isInMyAddrSpace & ~ipif.bus2ip_rnw, st_t.writeAck)
        ).Trans(st_t.writeAck,
            st_t.idle
        ).Trans(st_t.readDelay,
            st_t.rdData
        ).Trans(st_t.rdData,
            st_t.idle
        ).stateReg

        wAck = st._eq(st_t.writeAck)
        ipif.ip2bus_rdack(st._eq(st_t.rdData))
        ipif.ip2bus_wrack(wAck)
        ADDR_STEP = self._getAddrStep()
        dataToBus = ipif.ip2bus_data(None)
        for t in reversed(self._bramPortMapped):
            # map addr for bram ports
            _addr = t.bitAddr // ADDR_STEP
            _isMyAddr = isMyAddr(addr, _addr, t.bitAddrEnd // ADDR_STEP)
            port = self.getPort(t)

            self.propagateAddr(addr, ADDR_STEP, port.addr,
                               port.dout._dtype.bit_length(), t)

            port.en(_isMyAddr & ipif.bus2ip_cs)
            port.we(_isMyAddr & wAck)

            dataToBus = If(_isMyAddr,
                           ipif.ip2bus_data(port.dout)).Else(dataToBus)

            port.din(ipif.bus2ip_data)

        for t in self._directlyMapped:
            _addr = t.bitAddr // ADDR_STEP
            port = self.getPort(t)

            port.dout.vld(addr._eq(_addr) & ~ipif.bus2ip_rnw & wAck)
            port.dout.data(ipif.bus2ip_data)

        _isInBramFlags = []
        Switch(ipif.bus2ip_addr)\
        .addCases(
                [(t.bitAddr // ADDR_STEP, ipif.ip2bus_data(self.getPort(t).din))
                 for t in self._directlyMapped]
        ).Default(
            dataToBus
        )
Пример #19
0
    def _impl(self):
        self._parseTemplate()

        # build read data output mux

        def isMyAddr(addrSig, addr, end):
            return (addrSig >= addr) & (addrSig < end)

        st_t = HEnum('st_t', ['idle', 'readDelay', 'rdData'])
        bus = self.bus
        addr = bus.address
        addrVld = bus.read | bus.write

        st = FsmBuilder(self, st_t)\
            .Trans(st_t.idle,
                (addrVld & bus.read, st_t.rdData),
                (addrVld & bus.write, st_t.idle)
            ).Trans(st_t.readDelay,
                st_t.rdData
            ).Trans(st_t.rdData,
                st_t.idle
            ).stateReg

        wAck = True
        wr = bus.write & wAck
        isInAddrRange = (self.isInMyAddrRange(bus.address))

        If(isInAddrRange,
           bus.response(RESP_OKAY)).Else(bus.response(RESP_SLAVEERROR))
        bus.waitRequest(bus.read & ~st._eq(st_t.rdData))
        bus.readDataValid(st._eq(st_t.rdData))
        bus.writeResponseValid(wr)

        ADDR_STEP = self._getAddrStep()
        dataToBus = bus.readData(None)
        for t in reversed(self._bramPortMapped):
            # map addr for bram ports
            _addr = t.bitAddr // ADDR_STEP
            _isMyAddr = isMyAddr(addr, _addr, t.bitAddrEnd // ADDR_STEP)
            wasMyAddr = self._reg("wasMyAddr")
            If(st._eq(st_t.idle), wasMyAddr(_isMyAddr))
            port = self.getPort(t)

            self.propagateAddr(addr, ADDR_STEP, port.addr,
                               port.dout._dtype.bit_length(), t)

            port.en(_isMyAddr & addrVld)
            port.we(_isMyAddr & wr)

            dataToBus = If(wasMyAddr & st._eq(st_t.rdData),
                           bus.readData(port.dout)).Else(dataToBus)

            port.din(bus.writeData)

        for t in self._directlyMapped:
            _addr = t.bitAddr // ADDR_STEP
            port = self.getPort(t)

            port.dout.vld(addr._eq(_addr) & wr)
            port.dout.data(bus.writeData)

        _isInBramFlags = []
        Switch(bus.address)\
        .addCases(
            [(t.bitAddr // ADDR_STEP, bus.readData(self.getPort(t).din))
             for t in self._directlyMapped]
        ).Default(
            dataToBus
        )
Пример #20
0
    def _impl(self):
        self._parseTemplate()
        # build read data output mux

        def isMyAddr(addrSig, addr, end):
            return (addrSig >= addr) & (addrSig < end)

        st_t = HEnum('st_t', ['idle', 'readDelay', 'rdData'])
        bus = self.bus
        addr = bus.address
        addrVld = bus.read | bus.write

        st = FsmBuilder(self, st_t)\
            .Trans(st_t.idle,
                (addrVld & bus.read, st_t.rdData),
                (addrVld & bus.write, st_t.idle)
            ).Trans(st_t.readDelay,
                st_t.rdData
            ).Trans(st_t.rdData,
                st_t.idle
            ).stateReg

        wAck = True
        wr = bus.write & wAck
        isInAddrRange = (self.isInMyAddrRange(bus.address))

        If(isInAddrRange,
            bus.response(RESP_OKAY)
        ).Else(
            bus.response(RESP_SLAVEERROR)
        )
        bus.waitRequest(bus.read & ~st._eq(st_t.rdData))
        bus.readDataValid(st._eq(st_t.rdData))
        bus.writeResponseValid(wr)

        ADDR_STEP = self._getAddrStep()
        dataToBus = bus.readData(None)
        for t in reversed(self._bramPortMapped):
            # map addr for bram ports
            _addr = t.bitAddr // ADDR_STEP
            _isMyAddr = isMyAddr(addr, _addr, t.bitAddrEnd // ADDR_STEP)
            wasMyAddr = self._reg("wasMyAddr")
            If(st._eq(st_t.idle),
                wasMyAddr(_isMyAddr)
            )
            port = self.getPort(t)

            self.propagateAddr(addr, ADDR_STEP, port.addr,
                               port.dout._dtype.bit_length(), t)

            port.en(_isMyAddr & addrVld)
            port.we(_isMyAddr & wr)

            dataToBus = If(wasMyAddr & st._eq(st_t.rdData),
                           bus.readData(port.dout)
                        ).Else(
                            dataToBus
                        )

            port.din(bus.writeData)

        for t in self._directlyMapped:
            _addr = t.bitAddr // ADDR_STEP
            port = self.getPort(t)

            port.dout.vld(addr._eq(_addr) & wr)
            port.dout.data(bus.writeData)

        _isInBramFlags = []
        Switch(bus.address)\
        .addCases(
            [(t.bitAddr // ADDR_STEP, bus.readData(self.getPort(t).din))
             for t in self._directlyMapped]
        ).Default(
            dataToBus
        )
Пример #21
0
    def readPart(self, awAddr, w_hs):
        ADDR_STEP = self._getAddrStep()
        DW = int(self.DATA_WIDTH)
        # build read data output mux
        r = self.bus.r
        ar = self.bus.ar
        rSt_t = HEnum('rSt_t', ['rdIdle', 'bramRd', 'rdData'])
        isBramAddr = self._sig("isBramAddr")

        rSt = FsmBuilder(self, rSt_t, stateRegName='rSt')\
        .Trans(rSt_t.rdIdle,
            (ar.valid & ~isBramAddr & ~w_hs, rSt_t.rdData),
            (ar.valid & isBramAddr & ~w_hs, rSt_t.bramRd)
        ).Trans(rSt_t.bramRd,
            (~w_hs, rSt_t.rdData)
        ).Trans(rSt_t.rdData,
            (r.ready, rSt_t.rdIdle)
        ).stateReg

        arRd = rSt._eq(rSt_t.rdIdle)
        ar.ready(arRd & ~w_hs)

        # save ar addr
        arAddr = self._reg('arAddr', ar.addr._dtype)
        If(ar.valid & arRd, arAddr(ar.addr))

        isInAddrRange = self.isInMyAddrRange(arAddr)
        r.valid(rSt._eq(rSt_t.rdData))
        If(isInAddrRange, r.resp(RESP_OKAY)).Else(r.resp(RESP_SLVERR))
        if self._bramPortMapped:
            rdataReg = self._reg("rdataReg", r.data._dtype)
            _isInBramFlags = []
            # list of tuples (cond, rdataReg assignment)
            rregCases = []
            # index of bram from where we reads from
            bramRdIndx = self._reg("bramRdIndx",
                                   Bits(log2ceil(len(self._bramPortMapped))))
            bramRdIndxSwitch = Switch(bramRdIndx)
            for bramIndex, t in enumerate(self._bramPortMapped):
                port = self.getPort(t)

                # map addr for bram ports
                dstAddrStep = port.dout._dtype.bit_length()
                (_isMyArAddr,
                 arAddrConnect) = self.propagateAddr(ar.addr, ADDR_STEP,
                                                     port.addr, dstAddrStep, t)
                (_,
                 ar2AddrConnect) = self.propagateAddr(arAddr, ADDR_STEP,
                                                      port.addr, dstAddrStep,
                                                      t)
                (_isMyAwAddr,
                 awAddrConnect) = self.propagateAddr(awAddr, ADDR_STEP,
                                                     port.addr, dstAddrStep, t)
                prioritizeWrite = _isMyAwAddr & w_hs

                If(prioritizeWrite,
                   awAddrConnect).Elif(rSt._eq(rSt_t.rdIdle),
                                       arAddrConnect).Else(ar2AddrConnect)
                _isInBramFlags.append(_isMyArAddr)

                port.en((_isMyArAddr & ar.valid) | prioritizeWrite)
                port.we(prioritizeWrite)

                rregCases.append((_isMyArAddr, bramRdIndx(bramIndex)))
                bramRdIndxSwitch.Case(bramIndex, rdataReg(port.dout))

            bramRdIndxSwitch.Default(rdataReg(rdataReg))
            If(arRd, SwitchLogic(rregCases))
            isBramAddr(Or(*_isInBramFlags))

        else:
            rdataReg = None
            isBramAddr(0)

        directlyMappedWors = []
        for w, items in sorted(groupedby(
                self._directlyMapped, lambda t: t.bitAddr // DW *
            (DW // ADDR_STEP)),
                               key=lambda x: x[0]):
            lastBit = 0
            res = []
            items.sort(key=lambda t: t.bitAddr)
            for t in items:
                b = t.bitAddr % DW
                if b > lastBit:
                    # add padding
                    pad_w = b - lastBit
                    pad = Bits(pad_w).fromPy(None)
                    res.append(pad)
                    lastBit += pad_w
                din = self.getPort(t).din
                res.append(din)
                lastBit += din._dtype.bit_length()

            if lastBit != DW:
                # add at end padding
                pad = Bits(DW - lastBit).fromPy(None)
                res.append(pad)

            directlyMappedWors.append((w, Concat(*reversed(res))))

        Switch(arAddr).addCases([
            (w[0], r.data(w[1])) for w in directlyMappedWors
        ]).Default(r.data(rdataReg))
Пример #22
0
    def _translate_data_in(self, din: Handshaked) -> Hd44780CmdIntf:
        """
        Translates special characters to a LCD commands

        * '\\n' jump on next line and clean it with ' '
        * '\\f' clean the LCD and reset cursor position
        """
        if self.LCD_ROWS > 1:
            row = self._reg('row', Bits(log2ceil(self.LCD_ROWS - 1)), def_val=0)
            line_offsets = self._sig("line_offsets", Bits(8)[self.LCD_ROWS], def_val=[
                Hd44780Intf.CMD_DDRAM_ADDR_SET(i * self.LCD_COLS)
                for i in range(self.LCD_ROWS)
            ])
            line_offset = self._sig("line_offset", Bits(8))
            line_offset(line_offsets[row])
        else:
            # version without row register
            raise NotImplementedError()

        col = self._reg('col', Bits(log2ceil(self.LCD_COLS - 1)), def_val=0)

        dout = Hd44780CmdIntf()
        dout.DATA_WIDTH = self.LCD_DATA_WIDTH
        self.data_in_translated = dout

        new_line_fsm_t = HEnum("new_line_fsm_t", [
            'row_incr',
            'jmp_on_nextline',
            "clean_line",
            "jmp_on_line_start",
        ])
        new_line_fsm = FsmBuilder(self, new_line_fsm_t, "new_line_fsm")\
            .Trans(new_line_fsm_t.row_incr, (din.vld & din.data._eq(ord('\n')),
                                             new_line_fsm_t.jmp_on_nextline))\
            .Trans(new_line_fsm_t.jmp_on_nextline, (dout.rd,
                                                    new_line_fsm_t.clean_line))\
            .Trans(new_line_fsm_t.clean_line, (dout.rd & col._eq(self.LCD_COLS - 1),
                                               new_line_fsm_t.jmp_on_line_start))\
            .Trans(new_line_fsm_t.jmp_on_line_start, (dout.rd,
                                                      new_line_fsm_t.row_incr)).stateReg

        def set_out(d, rs, rw, long_wait):
            return [
                dout.d(d),
                dout.rs(rs),
                dout.rw(rw),
                dout.long_wait(long_wait),
            ]

        If(din.vld & din.data._eq(ord('\n')),
            # jump on next line and clean it with ' ' and jump back on first char
            Switch(new_line_fsm)\
            .Case(new_line_fsm_t.row_incr,
                row(row + 1),
                *set_out(None, None, None, None),
                din.rd(0),
                dout.vld(0),
            ).Case(new_line_fsm_t.jmp_on_nextline,
                col(0),
                *set_out(line_offset,
                         Hd44780Intf.RS_CONTROL,
                         Hd44780Intf.RW_WRITE, 0),
                din.rd(0),
                dout.vld(1),
            ).Case(new_line_fsm_t.clean_line,
                If(dout.rd,
                   col(col + 1),
                ),
                *set_out(Hd44780Intf.CHAR_MAP[' '],
                         Hd44780Intf.RS_DATA,
                         Hd44780Intf.RW_WRITE, 0),
            ).Case(new_line_fsm_t.jmp_on_line_start,
                *set_out(line_offset,
                         Hd44780Intf.RS_CONTROL,
                         Hd44780Intf.RW_WRITE, 0),
                *StreamNode([din], [dout]).sync(),
            ),
        ).Elif(din.vld & din.data._eq(ord('\f')),
            *set_out(Hd44780Intf.CMD_CLEAR_DISPLAY,
                     Hd44780Intf.RS_CONTROL,
                     Hd44780Intf.RW_WRITE, 1),
            *StreamNode([din], [dout]).sync(),
        ).Else(
            *set_out(din.data,
                     Hd44780Intf.RS_DATA,
                     Hd44780Intf.RW_WRITE, 0),
            *StreamNode([din], [dout]).sync(),
        )

        return dout
Пример #23
0
    def _impl(self):
        propagateClkRstn(self)
        self.axi_ep.bus(self.cntrl)

        ep = self.axi_ep.decoded
        id_reg_val = int.from_bytes("test".encode(), byteorder="little")
        ep.id_reg.din(id_reg_val)

        def connected_reg(name, input_=None, inputEn=None, fit=False):
            if input_ is not None:
                assert inputEn is not None

            port = getattr(ep, name)
            reg = self._reg(name, port.din._dtype)
            e = If(port.dout.vld,
                   connect(port.dout.data, reg, fit=fit)
                )
            if input_ is not None:
                e.Elif(inputEn,
                    connect(input_, reg, fit=fit)
                )
            port.din(reg)
            return reg

        cmdIn = ep.cmd_and_status.dout
        cmd = self._reg("reg_cmd", cmdIn.data._dtype, defVal=0)
        cmdVld = self._reg("reg_cmd_vld", defVal=0)
        If(cmdIn.vld,
           connect(cmdIn.data, cmd, fit=True)
        )
        partDone = self._sig("partDone")
        If(partDone,
           cmdVld(0)
        ).Elif(cmdIn.vld,
           cmdVld(1)
        )

        def cmd_en(cmd_code):
            return cmdVld & cmd._eq(cmd_code)

        state_t = HEnum("state_t",
                        ["ready", "wait_ar", "wait_aw",
                         "wait_w", "wait_b", "wait_r"])

        axi = self.m_axi
        st = FsmBuilder(self, state_t)\
            .Trans(state_t.ready,
                   (cmd_en(SEND_AW), state_t.wait_aw),
                   (cmd_en(SEND_AR), state_t.wait_ar),
                   (cmd_en(SEND_W), state_t.wait_w),
                   (cmd_en(RECV_R), state_t.wait_r),
                   (cmd_en(RECV_B), state_t.wait_b),
            ).Trans(state_t.wait_aw,
                (axi.aw.ready, state_t.ready)
            ).Trans(state_t.wait_ar,
                (axi.ar.ready, state_t.ready)
            ).Trans(state_t.wait_w,
                (axi.w.ready, state_t.ready)
            ).Trans(state_t.wait_r,
                (axi.r.valid, state_t.ready)
            ).Trans(state_t.wait_b,
                (axi.b.valid, state_t.ready)
            ).stateReg

        partDone((st._eq(state_t.wait_aw) & axi.aw.ready) |
                 (st._eq(state_t.wait_ar) & axi.ar.ready) |
                 (st._eq(state_t.wait_w) & axi.w.ready) |
                 (st._eq(state_t.wait_r) & axi.r.valid) |
                 (st._eq(state_t.wait_b) & axi.b.valid))

        ready = st._eq(state_t.ready)
        tmp = self._sig("tmp")
        tmp(ready & ~ep.cmd_and_status.dout.vld)
        connect(tmp, ep.cmd_and_status.din, fit=True)

        a_w_id = connected_reg("ar_aw_w_id")
        addr = connected_reg("addr")
        burst = connected_reg("burst")
        cache = connected_reg("cache")
        len_ = connected_reg("len")
        lock = connected_reg("lock")
        prot = connected_reg("prot")
        size = connected_reg("size")
        qos = connected_reg("qos")

        # aw/ar
        for p in [axi.aw, axi.ar]:
            p.id(a_w_id)
            p.addr(addr)
            p.burst(burst)
            p.cache(cache)
            p.len(len_)
            p.lock(lock)
            p.prot(prot)
            p.size(size)
            if hasattr(p, "qos"):
                p.qos(qos)

        aw_vld = st._eq(state_t.wait_aw)
        axi.aw.valid(aw_vld)
        ar_vld = st._eq(state_t.wait_ar)._reinterpret_cast(BIT)
        axi.ar.valid(ar_vld)

        r = axi.r
        r_rd = st._eq(state_t.wait_r)
        r_en = r.valid & r_rd
        connected_reg("r_id", r.id, r_en)
        connected_reg("r_data", r.data, r_en, fit=True)
        connected_reg("r_resp", r.resp, r_en)
        connected_reg("r_last", r.last, r_en)
        r.ready(r_rd)

        w = axi.w
        w_data = connected_reg("w_data", fit=True)
        w_last = connected_reg("w_last")
        w_strb = connected_reg("w_strb")
        if hasattr(w, "id"):
            w.id(a_w_id)
        connect(w_data, w.data, fit=True)
        w.strb(w_strb)
        w.last(w_last)
        w_vld = st._eq(state_t.wait_w)
        w.valid(w_vld)

        b = axi.b
        b_rd = st._eq(state_t.wait_b)
        connected_reg("b_id", b.id, b.valid & b_rd)
        connected_reg("b_resp")
        b.ready(b_rd)

        ep.hs.din(Concat(ar_vld, axi.ar.ready,
                         aw_vld, axi.aw.ready,
                         r.valid, r_rd,
                         b.valid, b_rd,
                         w_vld, w.ready))
Пример #24
0
    def writePart(self):
        DW = int(self.DATA_WIDTH)
        sig = self._sig
        reg = self._reg
        addrWidth = int(self.ADDR_WIDTH)
        ADDR_STEP = self._getAddrStep()

        wSt_t = HEnum('wSt_t', ['wrIdle', 'wrData', 'wrResp'])
        aw = self.bus.aw
        w = self.bus.w
        b = self.bus.b

        # write fsm
        wSt = FsmBuilder(self, wSt_t, "wSt")\
            .Trans(wSt_t.wrIdle,
                (aw.valid, wSt_t.wrData)
            ).Trans(wSt_t.wrData,
                (w.valid, wSt_t.wrResp)
            ).Trans(wSt_t.wrResp,
                (b.ready, wSt_t.wrIdle)
           ).stateReg

        awAddr = reg('awAddr', aw.addr._dtype)
        w_hs = sig('w_hs')

        awRd = wSt._eq(wSt_t.wrIdle)
        aw.ready(awRd)
        aw_hs = awRd & aw.valid

        wRd = wSt._eq(wSt_t.wrData)
        w.ready(wRd)

        w_hs(w.valid & wRd)

        # save aw addr
        If(aw_hs, awAddr(aw.addr)).Else(awAddr(awAddr))

        # output vld
        for t in self._directlyMapped:
            out = self.getPort(t).dout
            try:
                width = t.getItemWidth()
            except TypeError:
                width = t.bitAddrEnd - t.bitAddr

            if width > DW:
                raise NotImplementedError(
                    "Fields wider than DATA_WIDTH not supported yet", t)
            offset = t.bitAddr % DW
            out.data(w.data[(offset + width):offset])
            out.vld(w_hs & (
                awAddr._eq(vec(t.bitAddr // DW *
                               (DW // ADDR_STEP), addrWidth))))

        for t in self._bramPortMapped:
            din = self.getPort(t).din
            connect(w.data, din, fit=True)

        self.writeRespPart(awAddr, wSt._eq(wSt_t.wrResp))

        return awAddr, w_hs
Пример #25
0
    def writePart(self):
        DW = int(self.DATA_WIDTH)
        sig = self._sig
        reg = self._reg
        addrWidth = int(self.ADDR_WIDTH)
        ADDR_STEP = self._getAddrStep()

        wSt_t = HEnum('wSt_t', ['wrIdle', 'wrData', 'wrResp'])
        aw = self.bus.aw
        w = self.bus.w
        b = self.bus.b

        # write fsm
        wSt = FsmBuilder(self, wSt_t, "wSt")\
            .Trans(wSt_t.wrIdle,
                (aw.valid, wSt_t.wrData)
            ).Trans(wSt_t.wrData,
                (w.valid, wSt_t.wrResp)
            ).Trans(wSt_t.wrResp,
                (b.ready, wSt_t.wrIdle)
           ).stateReg

        awAddr = reg('awAddr', aw.addr._dtype)
        w_hs = sig('w_hs')

        awRd = wSt._eq(wSt_t.wrIdle)
        aw.ready(awRd)
        aw_hs = awRd & aw.valid

        wRd = wSt._eq(wSt_t.wrData)
        w.ready(wRd)

        w_hs(w.valid & wRd)

        # save aw addr
        If(aw_hs,
            awAddr(aw.addr)
        ).Else(
            awAddr(awAddr)
        )

        # output vld
        for t in self._directlyMapped:
            out = self.getPort(t).dout
            try:
                width = t.getItemWidth()
            except TypeError:
                width = t.bitAddrEnd - t.bitAddr

            if width > DW:
                raise NotImplementedError("Fields wider than DATA_WIDTH not supported yet", t)
            offset = t.bitAddr % DW
            out.data(w.data[(offset + width): offset])
            out.vld(w_hs & (awAddr._eq(vec(t.bitAddr // DW * (DW // ADDR_STEP),
                                           addrWidth))))

        for t in self._bramPortMapped:
            din = self.getPort(t).din
            connect(w.data, din, fit=True)

        self.writeRespPart(awAddr, wSt._eq(wSt_t.wrResp))

        return awAddr, w_hs
Пример #26
0
    def _impl(self):
        propagateClkRstn(self)
        self.axi_ep.bus(self.cntrl)

        ep = self.axi_ep.decoded
        id_reg_val = int.from_bytes("test".encode(), byteorder="little")
        ep.id_reg.din(id_reg_val)

        def connected_reg(name, input_=None, inputEn=None, fit=False):
            if input_ is not None:
                assert inputEn is not None

            port = getattr(ep, name)
            reg = self._reg(name, port.din._dtype)
            e = If(port.dout.vld, connect(port.dout.data, reg, fit=fit))
            if input_ is not None:
                e.Elif(inputEn, connect(input_, reg, fit=fit))
            port.din(reg)
            return reg

        cmdIn = ep.cmd_and_status.dout
        cmd = self._reg("reg_cmd", cmdIn.data._dtype, defVal=0)
        cmdVld = self._reg("reg_cmd_vld", defVal=0)
        If(cmdIn.vld, connect(cmdIn.data, cmd, fit=True))
        partDone = self._sig("partDone")
        If(partDone, cmdVld(0)).Elif(cmdIn.vld, cmdVld(1))

        def cmd_en(cmd_code):
            return cmdVld & cmd._eq(cmd_code)

        state_t = HEnum(
            "state_t",
            ["ready", "wait_ar", "wait_aw", "wait_w", "wait_b", "wait_r"])

        axi = self.m_axi
        st = FsmBuilder(self, state_t)\
            .Trans(state_t.ready,
                   (cmd_en(SEND_AW), state_t.wait_aw),
                   (cmd_en(SEND_AR), state_t.wait_ar),
                   (cmd_en(SEND_W), state_t.wait_w),
                   (cmd_en(RECV_R), state_t.wait_r),
                   (cmd_en(RECV_B), state_t.wait_b),
            ).Trans(state_t.wait_aw,
                (axi.aw.ready, state_t.ready)
            ).Trans(state_t.wait_ar,
                (axi.ar.ready, state_t.ready)
            ).Trans(state_t.wait_w,
                (axi.w.ready, state_t.ready)
            ).Trans(state_t.wait_r,
                (axi.r.valid, state_t.ready)
            ).Trans(state_t.wait_b,
                (axi.b.valid, state_t.ready)
            ).stateReg

        partDone((st._eq(state_t.wait_aw) & axi.aw.ready)
                 | (st._eq(state_t.wait_ar) & axi.ar.ready)
                 | (st._eq(state_t.wait_w) & axi.w.ready)
                 | (st._eq(state_t.wait_r) & axi.r.valid)
                 | (st._eq(state_t.wait_b) & axi.b.valid))

        ready = st._eq(state_t.ready)
        tmp = self._sig("tmp")
        tmp(ready & ~ep.cmd_and_status.dout.vld)
        connect(tmp, ep.cmd_and_status.din, fit=True)

        a_w_id = connected_reg("ar_aw_w_id")
        addr = connected_reg("addr")
        burst = connected_reg("burst")
        cache = connected_reg("cache")
        len_ = connected_reg("len")
        lock = connected_reg("lock")
        prot = connected_reg("prot")
        size = connected_reg("size")
        qos = connected_reg("qos")

        # aw/ar
        for p in [axi.aw, axi.ar]:
            p.id(a_w_id)
            p.addr(addr)
            p.burst(burst)
            p.cache(cache)
            p.len(len_)
            p.lock(lock)
            p.prot(prot)
            p.size(size)
            if hasattr(p, "qos"):
                p.qos(qos)

        aw_vld = st._eq(state_t.wait_aw)
        axi.aw.valid(aw_vld)
        ar_vld = st._eq(state_t.wait_ar)._reinterpret_cast(BIT)
        axi.ar.valid(ar_vld)

        r = axi.r
        r_rd = st._eq(state_t.wait_r)
        r_en = r.valid & r_rd
        connected_reg("r_id", r.id, r_en)
        connected_reg("r_data", r.data, r_en, fit=True)
        connected_reg("r_resp", r.resp, r_en)
        connected_reg("r_last", r.last, r_en)
        r.ready(r_rd)

        w = axi.w
        w_data = connected_reg("w_data", fit=True)
        w_last = connected_reg("w_last")
        w_strb = connected_reg("w_strb")
        if hasattr(w, "id"):
            w.id(a_w_id)
        connect(w_data, w.data, fit=True)
        w.strb(w_strb)
        w.last(w_last)
        w_vld = st._eq(state_t.wait_w)
        w.valid(w_vld)

        b = axi.b
        b_rd = st._eq(state_t.wait_b)
        connected_reg("b_id", b.id, b.valid & b_rd)
        connected_reg("b_resp")
        b.ready(b_rd)

        ep.hs.din(
            Concat(ar_vld, axi.ar.ready, aw_vld, axi.aw.ready, r.valid, r_rd,
                   b.valid, b_rd, w_vld, w.ready))
Пример #27
0
    def readPart(self, awAddr, w_hs):
        ADDR_STEP = self._getAddrStep()
        DW = int(self.DATA_WIDTH)
        # build read data output mux
        r = self.bus.r
        ar = self.bus.ar
        rSt_t = HEnum('rSt_t', ['rdIdle', 'bramRd', 'rdData'])
        isBramAddr = self._sig("isBramAddr")

        rSt = FsmBuilder(self, rSt_t, stateRegName='rSt')\
        .Trans(rSt_t.rdIdle,
            (ar.valid & ~isBramAddr & ~w_hs, rSt_t.rdData),
            (ar.valid & isBramAddr & ~w_hs, rSt_t.bramRd)
        ).Trans(rSt_t.bramRd,
            (~w_hs, rSt_t.rdData)
        ).Trans(rSt_t.rdData,
            (r.ready, rSt_t.rdIdle)
        ).stateReg

        arRd = rSt._eq(rSt_t.rdIdle)
        ar.ready(arRd & ~w_hs)

        # save ar addr
        arAddr = self._reg('arAddr', ar.addr._dtype)
        If(ar.valid & arRd,
            arAddr(ar.addr)
        )

        isInAddrRange = self.isInMyAddrRange(arAddr)
        r.valid(rSt._eq(rSt_t.rdData))
        If(isInAddrRange,
            r.resp(RESP_OKAY)
        ).Else(
            r.resp(RESP_SLVERR)
        )
        if self._bramPortMapped:
            rdataReg = self._reg("rdataReg", r.data._dtype)
            _isInBramFlags = []
            # list of tuples (cond, rdataReg assignment)
            rregCases = []
            # index of bram from where we reads from
            bramRdIndx = self._reg("bramRdIndx", Bits(
                log2ceil(len(self._bramPortMapped))))
            bramRdIndxSwitch = Switch(bramRdIndx)
            for bramIndex, t in enumerate(self._bramPortMapped):
                port = self.getPort(t)

                # map addr for bram ports
                dstAddrStep = port.dout._dtype.bit_length()
                (_isMyArAddr, arAddrConnect) = self.propagateAddr(
                    ar.addr, ADDR_STEP, port.addr, dstAddrStep, t)
                (_, ar2AddrConnect) = self.propagateAddr(
                    arAddr, ADDR_STEP, port.addr, dstAddrStep, t)
                (_isMyAwAddr, awAddrConnect) = self.propagateAddr(
                    awAddr, ADDR_STEP, port.addr, dstAddrStep, t)
                prioritizeWrite = _isMyAwAddr & w_hs

                If(prioritizeWrite,
                    awAddrConnect
                ).Elif(rSt._eq(rSt_t.rdIdle),
                    arAddrConnect
                ).Else(
                    ar2AddrConnect
                )
                _isInBramFlags.append(_isMyArAddr)

                port.en((_isMyArAddr & ar.valid) | prioritizeWrite)
                port.we(prioritizeWrite)

                rregCases.append((_isMyArAddr, bramRdIndx(bramIndex)))
                bramRdIndxSwitch.Case(bramIndex, rdataReg(port.dout))

            bramRdIndxSwitch.Default(rdataReg(rdataReg))
            If(arRd,
               SwitchLogic(rregCases)
            )
            isBramAddr(Or(*_isInBramFlags))

        else:
            rdataReg = None
            isBramAddr(0)

        directlyMappedWors = []
        for w, items in sorted(groupedby(self._directlyMapped,
                                         lambda t: t.bitAddr // DW * (DW // ADDR_STEP)),
                               key=lambda x: x[0]):
            lastBit = 0
            res = []
            items.sort(key=lambda t: t.bitAddr)
            for t in items:
                b = t.bitAddr % DW
                if b > lastBit:
                    # add padding
                    pad_w = b - lastBit
                    pad = Bits(pad_w).fromPy(None)
                    res.append(pad)
                    lastBit += pad_w
                din = self.getPort(t).din
                res.append(din)
                lastBit += din._dtype.bit_length()

            if lastBit != DW:
                # add at end padding
                pad = Bits(DW - lastBit).fromPy(None)
                res.append(pad)

            directlyMappedWors.append((w, Concat(*reversed(res))))

        Switch(arAddr).addCases(
            [(w[0], r.data(w[1]))
             for w in directlyMappedWors]
        ).Default(
            r.data(rdataReg)
        )
Пример #28
0
    def readPart(self, awAddr, w_hs):
        ADDR_STEP = self._getAddrStep()
        # build read data output mux
        r = self.bus.r
        ar = self.bus.ar
        rSt_t = HEnum('rSt_t', ['rdIdle', 'bramRd', 'rdData'])
        isBramAddr = self._sig("isBramAddr")

        rSt = FsmBuilder(self, rSt_t, stateRegName='rSt')\
        .Trans(rSt_t.rdIdle,
            (ar.valid & ~isBramAddr & ~w_hs, rSt_t.rdData),
            (ar.valid & isBramAddr & ~w_hs, rSt_t.bramRd)
        ).Trans(rSt_t.bramRd,
            (~w_hs, rSt_t.rdData)
        ).Trans(rSt_t.rdData,
            (r.ready, rSt_t.rdIdle)
        ).stateReg

        arRd = rSt._eq(rSt_t.rdIdle)
        ar.ready(arRd & ~w_hs)

        # save ar addr
        arAddr = self._reg('arAddr', ar.addr._dtype)
        If(ar.valid & arRd, arAddr(ar.addr))

        isInAddrRange = self.isInMyAddrRange(arAddr)
        r.valid(rSt._eq(rSt_t.rdData))
        self.driveResp(isInAddrRange, r.resp)
        if self._bramPortMapped:
            rdataReg = self._reg("rdataReg", r.data._dtype)
            _isInBramFlags = []
            # list of tuples (cond, rdataReg assignment)
            rregCases = []
            # index of bram from where we reads from
            bramRdIndx = self._reg("bramRdIndx",
                                   Bits(log2ceil(len(self._bramPortMapped))))
            bramRdIndxSwitch = Switch(bramRdIndx)
            for bramIndex, ((base, end), t) in enumerate(self._bramPortMapped):
                port = self.getPort(t)

                # map addr for bram ports
                dstAddrStep = port.dout._dtype.bit_length()
                (_isMyArAddr,
                 arAddrConnect) = self.propagateAddr(ar.addr, ADDR_STEP,
                                                     port.addr, dstAddrStep, t)
                (_,
                 ar2AddrConnect) = self.propagateAddr(arAddr, ADDR_STEP,
                                                      port.addr, dstAddrStep,
                                                      t)
                (_isMyAwAddr,
                 awAddrConnect) = self.propagateAddr(awAddr, ADDR_STEP,
                                                     port.addr, dstAddrStep, t)
                prioritizeWrite = w_hs & _isMyAwAddr

                If(prioritizeWrite,
                   awAddrConnect).Elif(rSt._eq(rSt_t.rdIdle),
                                       arAddrConnect).Else(ar2AddrConnect)
                _isInBramFlags.append(_isMyArAddr)

                port.en((ar.valid & _isMyArAddr) | prioritizeWrite)
                port.we(prioritizeWrite)

                rregCases.append((_isMyArAddr, bramRdIndx(bramIndex)))
                bramRdIndxSwitch.Case(bramIndex, rdataReg(port.dout))

            bramRdIndxSwitch.Default(rdataReg(rdataReg))
            If(arRd, SwitchLogic(rregCases))
            isBramAddr(Or(*_isInBramFlags))

        else:
            rdataReg = None
            isBramAddr(0)

        self.connect_directly_mapped_read(arAddr, r.data, r.data(rdataReg))
Пример #29
0
    def _impl(self):
        ALIGN_BITS = log2ceil(self.DATA_WIDTH // 8 - 1).val
        TIMEOUT_MAX = self.TIMEOUT - 1
        ITEMS = self.ITEMS
        buff = self.buff
        reqAck = self.wDatapump.ack
        req = self.wDatapump.req
        w = self.wDatapump.w

        propagateClkRstn(self)

        sizeOfitems = self._reg("sizeOfItems", Bits(
            buff.size._dtype.bit_length()))

        # aligned base addr
        baseAddr = self._reg("baseAddrReg", Bits(self.ADDR_WIDTH - ALIGN_BITS))
        If(self.baseAddr.dout.vld,
           baseAddr(self.baseAddr.dout.data[:ALIGN_BITS])
           )
        self.baseAddr.din(Concat(baseAddr, vec(0, ALIGN_BITS)))

        # offset in buffer and its complement
        offset_t = Bits(log2ceil(ITEMS + 1), signed=False)
        offset = self._reg("offset", offset_t, defVal=0)
        remaining = self._reg("remaining", Bits(
            log2ceil(ITEMS + 1), signed=False), defVal=ITEMS)
        connect(remaining, self.buff_remain, fit=True)

        addrTmp = self._sig("baseAddrTmp", baseAddr._dtype)
        addrTmp(baseAddr + fitTo(offset, baseAddr))

        # req values logic
        req.id(self.ID)
        req.addr(Concat(addrTmp, vec(0, ALIGN_BITS)))
        req.rem(0)

        sizeTmp = self._sig("sizeTmp", buff.size._dtype)

        assert req.len._dtype.bit_length() == buff.size._dtype.bit_length() - 1, (
            req.len._dtype.bit_length(), buff.size._dtype.bit_length())

        buffSizeAsLen = self._sig("buffSizeAsLen", buff.size._dtype)
        buffSizeAsLen(buff.size - 1)
        buffSize_tmp = self._sig("buffSize_tmp", remaining._dtype)
        connect(buff.size, buffSize_tmp, fit=True)

        endOfLenBlock = (remaining - 1) < buffSize_tmp

        remainingAsLen = self._sig("remainingAsLen", remaining._dtype)
        remainingAsLen(remaining - 1)

        If(endOfLenBlock,
            connect(remainingAsLen, req.len, fit=True),
            connect(remaining, sizeTmp, fit=True)
        ).Else(
            connect(buffSizeAsLen, req.len, fit=True),
            sizeTmp(buff.size)
        )

        lastWordCntr = self._reg("lastWordCntr", buff.size._dtype, 0)
        w_last = lastWordCntr._eq(1)
        w_ack = w.ready & buff.dataOut.vld

        # timeout logic
        timeoutCntr = self._reg("timeoutCntr", Bits(log2ceil(self.TIMEOUT), False),
                                defVal=TIMEOUT_MAX)
        # buffer is full or timeout
        beginReq = buff.size._eq(self.BUFF_DEPTH) | timeoutCntr._eq(0)
        reqAckHasCome = self._sig("reqAckHasCome")
        reqAckHasCome(reqAck.vld & reqAck.data._eq(self.ID))
        st = FsmBuilder(self, stT)\
            .Trans(stT.waitOnInput,
                (beginReq & req.rd, stT.waitOnDataTx)
            ).Trans(stT.waitOnDataTx,
                    (w_last & w_ack, stT.waitOnAck)
            ).Trans(stT.waitOnAck,
                    (reqAckHasCome, stT.waitOnInput)
            ).stateReg

        If(st._eq(stT.waitOnInput) & beginReq,  # timeout is counting only when there is pending data
            # start new request
            req.vld(1),
            If(req.rd,
                If(endOfLenBlock,
                   offset(0),
                   remaining(ITEMS)
                ).Else(
                    offset(offset + fitTo(buff.size, offset)),
                    remaining(remaining - fitTo(buff.size, remaining))
                ),
                sizeOfitems(sizeTmp),
                timeoutCntr(TIMEOUT_MAX)
            )
        ).Else(
            req.vld(0),
            If(buff.dataOut.vld & st._eq(stT.waitOnInput) & (timeoutCntr != 0),
               timeoutCntr(timeoutCntr - 1)
            )
        )

        reqAck.rd(st._eq(stT.waitOnAck))

        self.uploadedCntrHandler(st, reqAckHasCome, sizeOfitems)

        # it does not matter when lastWordCntr is changing when there is no
        # request
        startSendingData = st._eq(stT.waitOnInput) & beginReq & req.rd
        If(startSendingData,
            lastWordCntr(sizeTmp)
        ).Elif((lastWordCntr != 0) & w_ack,
            lastWordCntr(lastWordCntr - 1)
        )

        buff.dataIn(self.items)

        connect(buff.dataOut.data, w.data, fit=True)

        StreamNode(masters=[buff.dataOut],
                   slaves=[w]
                   ).sync(st._eq(stT.waitOnDataTx))
        w.strb(mask(w.strb._dtype.bit_length()))
        w.last(w_last)