Exemplo n.º 1
0
 def _declr(self):
     HandshakeSync._declr(self)
     args = HObjList()
     for a in self._exception.hw_args:
         _a = monitor_of(a)
         args.append(_a)
     self.args = args
Exemplo n.º 2
0
    def _declr(self) -> None:
        self._normalize_config()
        addClkRstn(self)

        slavePorts = HObjList()
        for _ in self.MASTERS:
            s = Mi32()
            s._updateParamsFrom(self)
            slavePorts.append(s)

        self.s = slavePorts

        masterPorts = HObjList()
        for _, size in self.SLAVES:
            m = Mi32()._m()
            m.ADDR_WIDTH = log2ceil(size - 1)
            m.DATA_WIDTH = self.DATA_WIDTH
            masterPorts.append(m)

        self.m = masterPorts

        # fifo which keeps index of slave for master read transaction
        # so the interconnect can delivery the read data to master
        # which asked for it
        f = self.r_data_order = HandshakedFifo(Handshaked)
        f.DEPTH = self.MAX_TRANS_OVERLAP
        f.DATA_WIDTH = log2ceil(len(self.SLAVES))
Exemplo n.º 3
0
    def _declr(self):
        BusInterconnect._normalize_config(self)
        self.connection_groups_r = BusInterconnectUtils._extract_separable_groups(
            self.MASTERS, self.SLAVES, READ)
        self.connection_groups_w = BusInterconnectUtils._extract_separable_groups(
            self.MASTERS, self.SLAVES, WRITE)
        super(AxiInterconnectMatrix, self)._declr()

        # instantiate sub interconnects for each independent master-slave connection
        # subgraph (r, w separately)
        self.sub_interconnect_connections = []
        r_interconnects = HObjList()
        masters_with_read_ch = set()
        slaves_with_read_ch = set()
        for r_group in self.connection_groups_r:
            master_indexes, slave_indexes = r_group
            masters_with_read_ch.update(master_indexes)
            slaves_with_read_ch.update(slave_indexes)

            inter = AxiInterconnectMatrixR(self.intfCls)
            con = self.configure_sub_interconnect(master_indexes,
                                                  slave_indexes, inter)
            r_interconnects.append(inter)
            self.sub_interconnect_connections.extend(con)

        masters_with_write_ch = set()
        slaves_with_write_ch = set()
        w_interconnects = HObjList()
        for w_group in self.connection_groups_w:
            master_indexes, slave_indexes = w_group
            masters_with_write_ch.update(master_indexes)
            slaves_with_write_ch.update(slave_indexes)

            inter = AxiInterconnectMatrixW(self.intfCls)
            con = self.configure_sub_interconnect(master_indexes,
                                                  slave_indexes, inter)
            w_interconnects.append(inter)
            self.sub_interconnect_connections.extend(con)

        with self._paramsShared(exclude=({"SLAVES", "MASTERS"}, set())):
            self.r_interconnects = r_interconnects
            self.w_interconnects = w_interconnects

        # dissable read/write unused channels on master/slave interfaces
        for m_i, m in enumerate(self.s):
            m.HAS_R = m_i in masters_with_read_ch
            m.HAS_W = m_i in masters_with_write_ch
            assert m.HAS_R or m.HAS_W, m_i

        for s_i, s in enumerate(self.m):
            s.HAS_R = s_i in slaves_with_read_ch
            s.HAS_W = s_i in slaves_with_write_ch
            assert s.HAS_R or s.HAS_W, s_i
Exemplo n.º 4
0
Arquivo: ram.py Projeto: mfkiwl/hwtLib
 def _declr_children(self):
     # for the case where this memory will be relized using multiple memory blocks
     children = HObjList()
     MAX_DW = self.MAX_BLOCK_DATA_WIDTH
     if MAX_DW is not None and MAX_DW < self.DATA_WIDTH:
         DW = self.DATA_WIDTH
         while DW > 0:
             c = self.__class__()
             c._updateParamsFrom(self, exclude=({"DATA_WIDTH"}, {}))
             c.DATA_WIDTH = min(DW, MAX_DW)
             if self.INIT_DATA is not None:
                 raise NotImplementedError()
             children.append(c)
             DW -= MAX_DW
     self.children = children
Exemplo n.º 5
0
    def _declr(self):
        AxiInterconnectCommon._declr(self, has_r=False, has_w=True)
        masters_for_slave = AxiInterconnectMatrixCrossbar._masters_for_slave(
            self.MASTERS, len(self.SLAVES))

        # fifo for master index for each slave so slave knows
        # which master did read and where is should send it
        order_m_index_for_s_data = HObjList()
        order_m_index_for_s_b = HObjList()
        for connected_masters in masters_for_slave:
            if len(connected_masters) > 1:
                f_w = HandshakedFifo(Handshaked)
                f_b = HandshakedFifo(Handshaked)
                for _f in [f_w, f_b]:
                    _f.DEPTH = self.MAX_TRANS_OVERLAP
                    _f.DATA_WIDTH = log2ceil(len(self.MASTERS))
            else:
                f_w, f_b = None, None
            order_m_index_for_s_data.append(f_w)
            order_m_index_for_s_b.append(f_b)
        self.order_m_index_for_s_data = order_m_index_for_s_data
        self.order_m_index_for_s_b = order_m_index_for_s_b
        # fifo for slave index for each master
        # so master knows where it should expect the data
        order_s_index_for_m_data = HObjList()
        order_s_index_for_m_b = HObjList()
        for connected_slaves in self.MASTERS:
            if len(connected_slaves) > 1:
                f_w = HandshakedFifo(Handshaked)
                f_b = HandshakedFifo(Handshaked)

                for f in [f_w, f_b]:
                    f.DEPTH = self.MAX_TRANS_OVERLAP
                    f.DATA_WIDTH = log2ceil(len(self.SLAVES))
            else:
                f_w, f_b = None, None
            order_s_index_for_m_data.append(f_w)
            order_s_index_for_m_b.append(f_b)
        self.order_s_index_for_m_data = order_s_index_for_m_data
        self.order_s_index_for_m_b = order_s_index_for_m_b

        AXI = self.intfCls
        with self._paramsShared():
            self.addr_crossbar = AxiInterconnectMatrixAddrCrossbar(AXI.AW_CLS)

        with self._paramsShared():
            c = self.data_crossbar = AxiInterconnectMatrixCrossbar(AXI.W_CLS)
            c.INPUT_CNT = len(self.MASTERS)
            W_OUTPUTS = [set() for _ in self.SLAVES]
            for m_i, accessible_slaves in enumerate(self.MASTERS):
                for s_i in accessible_slaves:
                    W_OUTPUTS[s_i].add(m_i)
            c.OUTPUTS = W_OUTPUTS

        with self._paramsShared():
            c = self.b_crossbar = AxiInterconnectMatrixCrossbarB(AXI.B_CLS)
            c.INPUT_CNT = len(self.SLAVES)
            c.OUTPUTS = self.MASTERS
Exemplo n.º 6
0
    def parseTemplate(self):
        t = self._structT
        try:
            t.bit_length()
            is_const_size_frame = True
        except TypeError:
            is_const_size_frame = False
        if is_const_size_frame:
            self.sub_t = []
            self.children = []
            super(AxiS_frameParser, self).parseTemplate()
        else:
            if self._tmpl or self._frames:
                raise NotImplementedError()

            children = HObjList()
            self.sub_t = sub_t = []
            is_const_sized = self.sub_t_is_const_sized = []
            is_padding = self.sub_t_is_padding = []
            separated = list(HdlType_separate(t, is_non_const_stream))
            if len(separated) > 1 or separated[0][0]:
                # it may be required to delegate this on children
                first = True
                for is_non_const_sized, s_t in separated:
                    _is_padding = is_only_padding(s_t)
                    if is_non_const_sized or (not first and _is_padding):
                        c = None
                    else:
                        c = self.__class__(s_t)
                    sub_t.append(s_t)
                    children.append(c)
                    first = False
                    is_padding.append(_is_padding)
                    is_const_sized.append(not is_non_const_sized)

                if len(is_const_sized) >= 2 and \
                        is_const_sized[0] and\
                        not is_const_sized[1]:
                    # we will parse const-size prefix and
                    # then there will be a variable size suffix
                    children[0].OVERFLOW_SUPPORT = True

                with self._paramsShared(exclude=({"OVERFLOW_SUPPORT", "T"}, {})):
                    self.children = children
Exemplo n.º 7
0
    def create_data_reg(self, name_prefix, clk=None, rst=None):
        """
        Create a registers for data signals with default values
        from :class:`hwt.synthesizer.unit.Unit` parameters and with specified clk/rst
        """
        regs = HObjList()
        def_vals = self.DATA_RESET_VAL
        d_sigs = self.get_data(self.dataIn)

        if def_vals is None or isinstance(def_vals, (int)):
            def_vals = [def_vals for _ in d_sigs]

        for d, def_val in zip(d_sigs, def_vals):
            r = self._reg(name_prefix + d._name,
                          d._dtype,
                          def_val=def_val,
                          clk=clk, rst=rst)
            regs.append(r)

        return regs
Exemplo n.º 8
0
    def _declr(self) -> None:
        self._normalize_config()
        addClkRstn(self)

        slavePorts = HObjList()
        for _ in self.MASTERS:
            s = Ipif()
            s._updateParamsFrom(self)
            slavePorts.append(s)

        self.s = slavePorts

        masterPorts = HObjList()
        for _, size in self.SLAVES:
            m = Ipif()._m()
            m.ADDR_WIDTH = log2ceil(size - 1)
            m.DATA_WIDTH = self.DATA_WIDTH
            masterPorts.append(m)

        self.m = masterPorts
Exemplo n.º 9
0
    def _declr(self):
        AxiInterconnectCommon._declr(self, has_r=True, has_w=False)
        masters_for_slave = AxiInterconnectMatrixCrossbar._masters_for_slave(
            self.MASTERS, len(self.SLAVES))

        # fifo for master index for each slave so slave knows
        # which master did read and where is should send it
        order_m_index_for_s_data = HObjList()
        for connected_masters in masters_for_slave:
            if len(connected_masters) > 1:
                f = HandshakedFifo(Handshaked)
                f.DEPTH = self.MAX_TRANS_OVERLAP
                f.DATA_WIDTH = log2ceil(len(self.MASTERS))
            else:
                f = None
            order_m_index_for_s_data.append(f)
        self.order_m_index_for_s_data = order_m_index_for_s_data
        # fifo for slave index for each master
        # so master knows where it should expect the data
        order_s_index_for_m_data = HObjList()
        for connected_slaves in self.MASTERS:
            if len(connected_slaves) > 1:
                f = HandshakedFifo(Handshaked)
                f.DEPTH = self.MAX_TRANS_OVERLAP
                f.DATA_WIDTH = log2ceil(len(self.SLAVES))
            else:
                f = None
            order_s_index_for_m_data.append(f)
        self.order_s_index_for_m_data = order_s_index_for_m_data

        with self._paramsShared():
            self.addr_crossbar = AxiInterconnectMatrixAddrCrossbar(
                self.intfCls.AR_CLS)

        with self._paramsShared():
            c = self.data_crossbar = AxiInterconnectMatrixCrossbar(
                self.intfCls.R_CLS)
            c.INPUT_CNT = len(self.SLAVES)
            c.OUTPUTS = self.MASTERS
Exemplo n.º 10
0
Arquivo: ram.py Projeto: mfkiwl/hwtLib
    def _declr_ports(self):
        PORTS = self.PORT_CNT
        with self._paramsShared():
            ports = HObjList()
            if isinstance(PORTS, int):
                for _ in range(PORTS):
                    p = self.PORT_CLS()
                    ports.append(p)
            else:
                for access_mode in PORTS:
                    p = self.PORT_CLS()
                    if access_mode == READ_WRITE:
                        pass
                    elif access_mode == READ:
                        p.HAS_W = False
                    elif access_mode == WRITE:
                        p.HAS_R = False
                    else:
                        raise ValueError(access_mode)

                    ports.append(p)
            self.port = ports
Exemplo n.º 11
0
    def _declr(self):
        addClkRstn(self)
        INTF_CLS = self.intfCls
        INPUT_CNT = self.INPUT_CNT
        OUTPUT_CNT = len(self.OUTPUTS)
        self.OUTS_FOR_IN = self._masters_for_slave(self.OUTPUTS,
                                                   self.INPUT_CNT)

        with self._paramsShared():
            self.dataIn = HObjList([INTF_CLS() for _ in range(INPUT_CNT)])

        with self._paramsShared():
            self.dataOut = HObjList(
                [INTF_CLS()._m() for _ in range(OUTPUT_CNT)])

        # master index for each slave so slave knows
        # which master did read and where is should send it
        order_dout_index_for_din_in = HObjList()
        for connected_outs in self.OUTS_FOR_IN:
            if len(connected_outs) > 1:
                f = Handshaked()
                f.DATA_WIDTH = log2ceil(OUTPUT_CNT)
            else:
                f = None
            order_dout_index_for_din_in.append(f)
        self.order_dout_index_for_din_in = order_dout_index_for_din_in

        order_din_index_for_dout_in = HObjList()
        # slave index for each master
        # so master knows where it should expect the data
        for connected_ins in self.OUTPUTS:
            if len(connected_ins) > 1:
                f = Handshaked()
                f.DATA_WIDTH = log2ceil(INPUT_CNT)
            else:
                f = None
            order_din_index_for_dout_in.append(f)
        self.order_din_index_for_dout_in = order_din_index_for_dout_in
Exemplo n.º 12
0
    def _declr(self) -> None:
        addClkRstn(self)

        slavePorts = HObjList()
        for _, features in self._masters:
            if features is not ACCESS_RW:
                raise NotImplementedError(features)
            m = Ipif()
            m._updateParamsFrom(self)
            slavePorts.append(m)

        self.s = slavePorts

        masterPorts = HObjList()
        for _, size, features in self._slaves:
            if features is not ACCESS_RW:
                raise NotImplementedError(features)
            s = Ipif()._m()
            s.ADDR_WIDTH.set(log2ceil(size - 1))
            s._replaceParam(s.DATA_WIDTH, self.DATA_WIDTH)
            masterPorts.append(s)

        self.m = masterPorts
Exemplo n.º 13
0
    def _declr(self) -> None:
        addClkRstn(self)

        slavePorts = HObjList()
        for _, features in self._masters:
            if features is not ACCESS_RW:
                raise NotImplementedError(features)
            m = Ipif()
            m._updateParamsFrom(self)
            slavePorts.append(m)

        self.s = slavePorts

        masterPorts = HObjList()
        for _, size, features in self._slaves:
            if features is not ACCESS_RW:
                raise NotImplementedError(features)
            s = Ipif()._m()
            s.ADDR_WIDTH.set(log2ceil(size - 1))
            s._replaceParam(s.DATA_WIDTH, self.DATA_WIDTH)
            masterPorts.append(s)

        self.m = masterPorts
Exemplo n.º 14
0
    def delegate_to_children(self):
        """
        For the cases where output frames contains the streams which does
        not have start aligned to a frame word boundary, we have to build
        rest of the frame in child FrameForge and then instantiate
        AxiS_FrameJoin which will join such a unaligned frames together.
        """
        Cls = self.__class__
        assert len(self.sub_t) > 1, "We need to delegate to children only " \
            "if there is something which we can't do in this comp. directly"
        children = HObjList()
        for t in self.sub_t:
            _t = _get_only_stream(t)
            if _t is None:
                # we need a child to build a sub frame
                c = Cls(t)
                c.USE_KEEP = self.USE_STRB | self.DATA_WIDTH != 8
            else:
                # we will connect stream directly
                c = None

            children.append(c)

        with self._paramsShared(
                exclude=({"USE_KEEP", "USE_STRB", *TYPE_CONFIG_PARAMS_NAMES},
                         {})):
            self.children = children

        fjoin = AxiS_FrameJoin()
        sub_t_flatten = [to_primitive_stream_t(s_t) for s_t in self.sub_t]
        fjoin.T = HStruct(*((s_t, f"frame{i:d}")
                            for i, s_t in enumerate(sub_t_flatten)))
        fjoin._updateParamsFrom(self, exclude=({"USE_KEEP", "T"}, {}))
        # has to have keep, because we know that atleast one output will
        # have unaligned start
        fjoin.USE_KEEP = True
        self.frame_join = fjoin

        dout = self.dataOut
        if not self.USE_KEEP:
            exclude = (fjoin.dataOut.keep, )
        else:
            exclude = ()

        dout(fjoin.dataOut, exclude=exclude)

        propagateClkRstn(self)
        for i, c in enumerate(children):
            if c is None:
                # find the input stream
                _t, child_out = drill_down_in_HStruct_fields(
                    self.sub_t[i], self.dataIn)
                assert isinstance(_t, HStream)
            else:
                # connect children inputs
                connect_optional_with_best_effort_axis_mask_propagation(
                    self.dataIn, c.dataIn)
                child_out = c.dataOut

            # join children output streams to output
            fj_in = fjoin.dataIn[i]
            if fj_in.USE_KEEP and not child_out.USE_KEEP:
                if child_out.USE_STRB:
                    exclude = {child_out.strb, fj_in.keep}
                    fj_in.keep(child_out.strb)
                    if fj_in.USE_STRB:
                        fj_in.strb(child_out.strb)
                else:
                    exclude = {fj_in.keep}
                    keep_all = mask(fj_in.keep._dtype.bit_length())
                    fj_in.keep(keep_all)
                    if fj_in.USE_STRB:
                        fj_in.strb(keep_all)
            elif not self.USE_STRB and child_out.USE_STRB:
                exclude = (child_out.strb, )
            else:
                exclude = ()

            fj_in(child_out, exclude=exclude)
Exemplo n.º 15
0
    def _impl(self):
        REG_IN = self.REG_IN
        REQUIRES_CASCADE = self.REG_OUT and self.DATA_WIDTH > 48

        dsps = HObjList()
        for i in range(ceil(self.DATA_WIDTH / 48)):
            dsp = DSP48E1()
            dsp.A_INPUT = "DIRECT"
            dsp.B_INPUT = "DIRECT"
            dsp.USE_DPORT = "FALSE"

            dsp.ACASCREG = \
            dsp.ALUMODEREG = \
            dsp.AREG = \
            dsp.BCASCREG = \
            dsp.BREG = \
            dsp.CARRYINSELREG = \
            dsp.CREG = int(REG_IN or (REQUIRES_CASCADE and i > 0))

            dsp.ADREG = 0
            dsp.CARRYINSELREG = 0
            dsp.DREG = 0
            dsp.INMODEREG = 0
            dsp.MREG = 0
            dsp.OPMODEREG = 1
            dsp.PREG = int(self.REG_OUT)
            dsp.USE_MULT = "NONE"
            dsp.USE_SIMD = "ONE48"
            dsps.append(dsp)

        self.dsp = dsps

        carry = 0
        carry_column = 0
        dsp_outputs = []
        din = self.data_in
        dout = self.data_out
        dsp_clock_enables = []
        dsp_inputs = []
        for i, dsp in enumerate(dsps):
            offset = i * 48
            width = min(48, self.DATA_WIDTH - offset)
            if width <= 18:
                a = 0
                b = din.b[offset + width:offset]
            else:
                a = din.b[offset + width:18 + offset]
                b = din.b[offset + 18:offset]

            c = din.a[offset + width:offset]
            dsp_inputs.append((a, b, c))

        # register to wait 1 clock before 1st operation to load operation and operand selection registers
        mode_preload = self._reg("mode_preload", def_val=1)
        mode_preload(0)
        if REQUIRES_CASCADE:
            # cascade is required because carry out signal has register and thus the input data
            # to a next DSP has to be delayed
            assert self.REG_OUT
            stage_cnt = int(self.REG_IN) + int(self.REG_OUT) + ceil(self.DATA_WIDTH / 48) - 1
            clock_enables, _, in_ready, out_valid = generate_handshake_pipe_cntrl(
                self, stage_cnt, "pipe_reg", din.vld & ~mode_preload, dout.rd)

            delayed_dsp_inputs = []
            for i, (dsp, (a, b, c)) in enumerate(zip(dsps, dsp_inputs)):
                if self.REG_IN:
                    input_ces = clock_enables[:i]
                    ce_0 = clock_enables[i]
                    ce_1 = clock_enables[i + 1]
                else:
                    if i == 0:
                        # :note: only first does not have in registers
                        ce_0 = 1
                        ce_1 = clock_enables[i]
                        input_ces = []
                    else:
                        ce_0 = clock_enables[i - 1]
                        ce_1 = clock_enables[i]
                        input_ces = clock_enables[:i - 1] # because the last register is a part of DPS

                dsp_clock_enables.append((ce_0, ce_1))

                a_delayed = self.postpone_val(a, input_ces, f"a{i:d}_")
                b_delayed = self.postpone_val(b, input_ces, f"b{i:d}_")
                c_delayed = self.postpone_val(c, input_ces, f"c{i:d}_")
                delayed_dsp_inputs.append((a_delayed, b_delayed, c_delayed))

            dsp_inputs = delayed_dsp_inputs
        else:
            stage_cnt = int(self.REG_IN) + int(self.REG_OUT)
            clock_enables, _, in_ready, out_valid = generate_handshake_pipe_cntrl(
                self, stage_cnt, "pipe_reg", din.vld & ~mode_preload, dout.rd)

            if self.REG_IN:
                ce_0 = clock_enables[0]
            else:
                ce_0 = 1

            if self.REG_OUT:
                if self.REG_IN:
                    ce_1 = clock_enables[1]
                else:
                    ce_1 = clock_enables[0]
            else:
                ce_1 = 1

            for i, dsp in enumerate(dsps):
                dsp_clock_enables.append((mode_preload | ce_0, mode_preload | ce_1))

        dout.vld(out_valid & ~mode_preload)
        din.rd(in_ready & ~mode_preload)

        for i, (dsp, (ce_0, ce_1), (a, b, c)) in enumerate(zip(dsps, dsp_clock_enables, dsp_inputs)):
            offset = i * 48
            width = min(48, self.DATA_WIDTH - offset)

            dsp.CLK(self.clk)
            dsp.ACIN(0)
            dsp.BCIN(0)
            dsp.MULTSIGNIN(1)
            dsp.PCIN(0)
            dsp.CEINMODE(1)
            self.set_mode(dsp)
            dsp.RSTINMODE(0)

            if i == 0:
                dsp.CARRYINSEL(CARRYIN_SEL.CARRYIN.value)
                dsp.CARRYIN(carry)
                dsp.CARRYCASCIN(carry_column)
                carry = dsp.CARRYOUT[3]
                carry_column = dsp.CARRYCASCOUT
            else:
                dsp.CARRYINSEL(CARRYIN_SEL.CARRYCASCIN.value)
                dsp.CARRYIN(0)
                dsp.CARRYCASCIN(carry_column)
                carry_column = dsp.CARRYCASCOUT

            if width <= 18:
                assert isinstance(a, int) and a == 0, a
                dsp.A(a)
                dsp.B(fitTo(b, dsp.B, shrink=False))
                dsp.C(fitTo(c, dsp.C, shrink=False))
            elif width < 48:
                dsp.A(fitTo(a, dsp.A, shrink=False))
                dsp.B(b)
                dsp.C(fitTo(c, dsp.C, shrink=False))
            else:
                dsp.A(a)
                dsp.B(b)
                dsp.C(c)

            dsp.D(0)
            dsp_outputs.append(dsp.P[width:])

            for _ce in [
                    dsp.CEA1,
                    dsp.CEA2,
                    dsp.CEALUMODE,
                    dsp.CEB2,
                    dsp.CEB1,
                    dsp.CEC,
                    dsp.CECARRYIN,
                    dsp.CECTRL,
                ]:
                _ce(ce_0)
            for _ce in [dsp.CEAD, dsp.CED, dsp.CEM]:
                _ce(1)

            dsp.CEP(ce_1)

            for _rst in [dsp.RSTA,
                dsp.RSTALLCARRYIN,
                dsp.RSTALUMODE,
                dsp.RSTB,
                dsp.RSTC,
                dsp.RSTCTRL,
                dsp.RSTD,
                dsp.RSTM,
                dsp.RSTP,]:
                _rst(~self.rst_n)

        if REQUIRES_CASCADE:
            delayed_dsp_outputs = []
            max_delay = len(dsp_outputs) - 1
            for i, out in enumerate(dsp_outputs):
                delay = max_delay - i
                if delay > 0:
                    # select n last
                    ces = clock_enables[-delay:]
                    delayed_out = self.postpone_val(out, ces, f"out_delay_{i:d}")
                else:
                    delayed_out = out
                delayed_dsp_outputs.append(delayed_out)
            dsp_outputs = delayed_dsp_outputs
        dout.data(Concat(*reversed(dsp_outputs)))