Esempio n. 1
0
def simplify_indices_F(F, coords):
    # Safety check: Clearly if it's not the identity it cannot be equal to ()
    R = get_R_from_F_coords(F, coords)
    if not (R == F):
        return coords

    # generic test
    i0 = get_id_indices(F)
    # compose
    i0coords = compose_indices(F, i0, coords, list)
    if i0 == i0coords:
        return ()

    mcdp_dev_warning(
        'simplify_indices_F(): Note that none of this is ever taken(!).')
    if coords == [0] and len(F) == 1:
        return ()
    if coords == [0, 1] and len(F) == 2:
        return ()
    if coords == [0, (1, )] and len(F) == 2:
        return ()
    if coords == [0, 1, 2] and len(F) == 3:
        return ()

    mcdp_dev_warning('need a double check here')
    if coords == [[(0, 0)], [(1, 0)]]:
        return ()

    if coords == [[(0, 0)], [(1, 0), (1, 1)]]:
        return ()

    # [[(0, 1)], [(1, 0), (0, 0)]]
    return coords
Esempio n. 2
0
    def _execute(self, dp1, dp2):
        from mcdp_dp.dp_series_simplification import unwrap_as_series_start_last
        dp2_start, dp2_last = unwrap_as_series_start_last(dp2)
        a = dp2_last.coords
        R = Parallel(dp1, dp2_start).get_res_space()
        coords0 = compose_indices(R, 1, a, list)
        coords = [0, coords0]
        m = Mux(R, coords)
        x = make_parallel(dp1, dp2_start)

        from .dp_series_simplification import make_series
        return make_series(x, m)
Esempio n. 3
0
def mux_composition(dp1, dp2):
    try:
        dp0 = Series(dp1, dp2)

        F = dp1.get_fun_space()
        c1 = dp1.coords
        c2 = dp2.coords
        coords = compose_indices(F, c1, c2, list)
        coords = simplify_indices_F(F, coords)

        res = Mux(F, coords)
        assert res.get_res_space() == dp0.get_res_space()

        return res
    except DPInternalError as e:  # pragma: no cover
        msg = 'Cannot create shortcut.'
        raise_wrapped(DPInternalError,
                      e,
                      msg,
                      dp1=dp1.repr_long(),
                      dp2=dp2.repr_long())
Esempio n. 4
0
def make_series(dp1, dp2):
    """ Creates a Series if needed.
        Simplifies the identity and muxes """
    if disable_optimization:  # pragma: no cover
        return Series(dp1, dp2)
    # first, check that the series would be created correctly

    # Series(X(F,R), Terminator(R)) => Terminator(F)
    # but X not loop

    #     if is_equiv_to_terminator(dp2) and isinstance(dp1, Mux):
    #         res = Terminator(dp1.get_fun_space())
    #         assert res.get_fun_space() == dp1.get_fun_space()
    #         return res

    if equiv_to_identity(dp1):
        return dp2

    if equiv_to_identity(dp2):
        return dp1

    if isinstance(dp1, Parallel) and isinstance(dp2, Parallel):
        a = make_series(dp1.dp1, dp2.dp1)
        b = make_series(dp1.dp2, dp2.dp2)
        return make_parallel(a, b)

    # TODO: comment this, you get an error
    if isinstance(dp1, Mux) and isinstance(dp2, Mux):
        return mux_composition(dp1, dp2)

    if isinstance(dp1, Mux):

        def has_null_fun(dp):
            F = dp.get_fun_space()
            return isinstance(F, PosetProduct) and len(F) == 0

        if isinstance(dp2, Parallel):
            if isinstance(dp2.dp1, Identity) and has_null_fun(dp2.dp1):
                assert len(
                    dp1.coords) == 2  # because it is followed by parallel
                assert dp1.coords[0] == []  # because it's null
                x = dp1.coords[1]
                A = Mux(dp1.get_fun_space(), x)
                B = dp2.dp2
                C = Mux(B.get_res_space(), [[], ()])
                return make_series(make_series(A, B), C)

            if isinstance(dp2.dp2, Identity) and has_null_fun(dp2.dp2):
                assert len(
                    dp1.coords) == 2  # because it is followed by parallel
                assert dp1.coords[1] == []  # because it's null
                x = dp1.coords[0]
                A = Mux(dp1.get_fun_space(), x)
                B = dp2.dp1
                C = Mux(B.get_res_space(), [(), []])
                return make_series(make_series(A, B), C)

        if isinstance(dp2, Series):
            dps = unwrap_series(dp2)

            def has_null_identity(dp):
                assert isinstance(dp, Parallel)
                if isinstance(dp.dp1, Identity) and has_null_fun(dp.dp1):
                    return True
                if isinstance(dp.dp2, Identity) and has_null_fun(dp.dp2):
                    return True
                return False

            if isinstance(dps[0], Parallel) and has_null_identity(dps[0]):
                first = make_series(dp1, dps[0])
                rest = reduce(make_series, dps[1:])
                return make_series(first, rest)

    # bring the mux outside the parallel
    #                   | - Mux(c) - p1
    #  Mux([a,b]) ----> |
    #                   | -
    #                     | - p1
    #  Mux([a*c,b]) ----> |
    #                     |
    if isinstance(dp1, Mux) and isinstance(dp2, Parallel) \
            and isinstance(unwrap_series(dp2.dp1)[0], Mux):

        unwrapped = unwrap_series(dp2.dp1)
        first_mux = unwrapped[0]
        assert isinstance(first_mux, Mux)

        coords = dp1.coords
        assert isinstance(coords, list) and len(coords) == 2, coords

        F = dp1.get_fun_space()
        coords2 = [
            compose_indices(F, coords[0], first_mux.coords, list), coords[1]
        ]
        m2 = Mux(F, coords2)

        rest = wrap_series(first_mux.get_res_space(), unwrapped[1:])

        res = make_series(m2, make_parallel(rest, dp2.dp2))

        if do_extra_checks():
            check_same_spaces(Series(dp1, dp2), res)
        return res

    if isinstance(dp1, Mux) and isinstance(dp2, Parallel) \
            and isinstance(unwrap_series(dp2.dp2)[0], Mux):

        unwrapped = unwrap_series(dp2.dp2)
        first_mux = unwrapped[0]
        assert isinstance(first_mux, Mux)

        coords = dp1.coords
        assert isinstance(coords, list) and len(coords) == 2, coords

        F = dp1.get_fun_space()
        coords2 = [
            coords[0],
            compose_indices(F, coords[1], first_mux.coords, list)
        ]
        m2 = Mux(F, coords2)

        rest = wrap_series(first_mux.get_res_space(), unwrapped[1:])

        res = make_series(m2, make_parallel(dp2.dp1, rest))

        if do_extra_checks():
            check_same_spaces(Series(dp1, dp2), res)
        return res

    #     print('Cannot simplify:')
    #     print(' dp1: %s' % dp1)
    #     print(' dp2: %s' % dp2)
    #     print('\n- '.join([str(x) for x in unwrap_series(a)]))

    dp1s = unwrap_series(dp1)
    dp2s = unwrap_series(dp2)

    for rule in rules:
        # [dp1s[:-1] dp1s[-1]] --- [dp2s[0] dp2s[1:]]
        if rule.applies(dp1s[-1], dp2s[0]):
            # logger.debug('Applying series simplification rule %s' % type(rule).__name__)
            r = rule.execute(dp1s[-1], dp2s[0])
            try:
                check_same_fun(r, dp1s[-1])
                check_same_res(r, dp2s[0])
            except Exception as e:
                msg = 'Invalid result of simplification rule.'
                raise_wrapped(DPInternalError,
                              e,
                              msg,
                              rule=rule,
                              result=r.repr_long())

            first = wrap_series(dp1.get_fun_space(), dp1s[:-1])
            rest = wrap_series(dp2s[0].get_fun_space(), dp2s[1:])
            return make_series(first, make_series(r, rest))

    return Series(dp1, dp2)