Beispiel #1
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)
Beispiel #2
0
    def translate_addr_signal(self, mem_map, sig_in, sig_out):
        cases = []
        AW = sig_in._dtype.bit_length()

        for (offset_in, size, offset_out) in mem_map:
            in_is_aligned = offset_in % size == 0 and isPow2(size)
            out_is_aligned = offset_out % size == 0 and isPow2(size)
            if in_is_aligned:
                L = (size - 1).bit_length()
                en_sig = sig_in[:L]._eq(offset_in >> L)
                _sig_in = sig_in[L:]
                if out_is_aligned:
                    addr_drive = Concat(
                        Bits(AW - L).from_py(offset_out), _sig_in)
                else:
                    addr_drive = Concat(Bits(AW - L).from_py(0),
                                        _sig_in) + offset_out
            else:
                en_sig = inRange(sig_in, offset_in, offset_in + size)
                if offset_in == offset_out:
                    addr_drive = sig_in
                elif offset_in < offset_out:
                    addr_drive = sig_in + (offset_out - offset_in)
                else:
                    # offset_in > offset_out:
                    addr_drive = sig_in - (offset_in - offset_out)
            cases.append((en_sig, sig_out(addr_drive)))
        SwitchLogic(cases, default=sig_out(sig_in))
Beispiel #3
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)
Beispiel #4
0
    def propagateAddr(self, src_addr_sig: RtlSignal, src_addr_step: int,
                      dst_addr_sig: RtlSignal, dst_addr_step: int,
                      transTmpl: TransTmpl):
        """
        :param src_addr_sig: input signal with address
        :param src_addr_step: how many bits is addressing one unit of src_addr_sig
        :param dst_addr_sig: output signal for address
        :param dst_addr_step: how many bits is addressing one unit of dst_addr_sig
        :param transTmpl: TransTmpl which has meta-informations
            about this address space transition
        """
        IN_W = src_addr_sig._dtype.bit_length()

        # _prefix = transTmpl.getMyAddrPrefix(src_addr_step)
        assert dst_addr_step % src_addr_step == 0
        if not isinstance(transTmpl.dtype, HArray):
            raise TypeError(transTmpl.dtype)
        assert transTmpl.bitAddr % dst_addr_step == 0, (
            f"Has to be addressable by address with this step ({transTmpl})")

        addrIsAligned = transTmpl.bitAddr % transTmpl.bit_length() == 0
        bitsForAlignment = AddressStepTranslation(src_addr_step,
                                                  dst_addr_step).align_bits
        bitsOfSubAddr = ((transTmpl.bitAddrEnd - transTmpl.bitAddr - 1) //
                         dst_addr_step).bit_length()

        if addrIsAligned:
            bitsOfAddr = bitsOfSubAddr + bitsForAlignment
            bitsOfPrefix = IN_W - bitsOfAddr
            prefix = (transTmpl.bitAddr // src_addr_step) >> bitsOfAddr
            if bitsOfPrefix == 0:
                addrIsInRange = True
            else:
                addrIsInRange = src_addr_sig[:(IN_W -
                                               bitsOfPrefix)]._eq(prefix)
            addr_tmp = src_addr_sig
        else:
            _addr = transTmpl.bitAddr // src_addr_step
            _addrEnd = transTmpl.bitAddrEnd // src_addr_step
            addrIsInRange = inRange(src_addr_sig, _addr, _addrEnd)
            addr_tmp = self._sig(dst_addr_sig._name + "_addr_tmp",
                                 Bits(self.ADDR_WIDTH))
            addr_tmp(src_addr_sig - _addr)

        addr_h = bitsOfSubAddr + bitsForAlignment
        connectedAddr = dst_addr_sig(addr_tmp[addr_h:bitsForAlignment])

        return (addrIsInRange, connectedAddr)
Beispiel #5
0
 def isInMyAddrRange(self, addr_sig):
     return inRange(addr_sig, self._ADDR_MIN, self._ADDR_MAX)
Beispiel #6
0
 def translate_addr_val(self, mem_map, addr: int):
     for (offset_in, size, offset_out) in mem_map:
         if inRange(addr, offset_in, offset_in + size):
             return addr - (offset_in - offset_out)
     return addr