Кратчайший путь через диаграмму состояний - PullRequest
0 голосов
/ 02 апреля 2020

У меня есть диаграмма состояний, по которой я хочу перемещаться:

JTAG tap controller diagram

Он получил 6 устойчивых состояний (состояния, которые имеют только 1 возможных следующих состояний ), а остальные состояния используются для перехода из одного состояния в другое (2 возможных следующих состояния). Я хочу написать функцию, которая принимает текущее состояние и конечное состояние и возвращает байт [] с 0 и 1, которые используются для перехода из начального в конечное состояние. Я хочу, чтобы метод нашел максимально быстрый путь к месту назначения.

У меня были некоторые мысли относительно того, как решить эту проблему, но я не думал о хорошем (и желательно элегантном) решении.

  1. Состояние может иметь 1 или 2 следующих состояния - состояние может быть сохранено в виде строкового массива, где в массиве перечислены следующие состояния (может быть гораздо лучший способ хранения информации комбинаций состояния / следующего состояния, пожалуйста, просветите меня!)
  2. Возможно, я смогу найти конечное состояние с помощью рекурсивных функций, но я не уверен, как.
  3. Через поиск Google о том, как Решив эту проблему, я столкнулся с алгоритмом Дейкстры. Мне кажется, что этот алгоритм может быть бесполезен в моем сценарии - или что?

Я думал о его жестком кодировании, но это делает функцию ужасно длинной. Конечно, должен быть разумный способ сделать это?

Любая помощь будет высоко ценится!

РЕДАКТИРОВАТЬ:

private STATE TapStateNext(STATE state, bool tms)
        {
            switch (tapState)
            {
                case STATE.TEST_LOGIC_RESET:
                    return tms ? STATE.TEST_LOGIC_RESET_B : STATE.RUN_TEST_IDLE;
                case STATE.TEST_LOGIC_RESET_B:
                    return tms ? STATE.TEST_LOGIC_RESET_A : STATE.RUN_TEST_IDLE;
                case STATE.RUN_TEST_IDLE:
                    return tms ? STATE.SELECT_DR_SCAN : state;
                case STATE.SELECT_DR_SCAN:
                    return tms ? STATE.SELECT_IR_SCAN : STATE.CAPTURE_DR;
                case STATE.SELECT_IR_SCAN:
                    return tms ? STATE.TEST_LOGIC_RESET_A : STATE.CAPTURE_IR;
                case STATE.CAPTURE_DR:
                    return tms ? STATE.EXIT1_DR : STATE.SHIFT_DR;
                case STATE.SHIFT_DR:
                    return tms ? STATE.EXIT1_DR : state;
                case STATE.EXIT1_DR:
                    return tms ? STATE.UPDATE_DR : STATE.PAUSE_DR;
                case STATE.PAUSE_DR:
                    return tms ? STATE.EXIT2_DR : state;
                case STATE.EXIT2_DR:
                    return tms ? STATE.UPDATE_DR : STATE.SHIFT_DR;
                case STATE.UPDATE_DR:
                    return tms ? STATE.SELECT_DR_SCAN : STATE.RUN_TEST_IDLE;
                case STATE.CAPTURE_IR:
                    return tms ? STATE.EXIT1_IR : STATE.SHIFT_IR;
                case STATE.SHIFT_IR:
                    return tms ? STATE.EXIT1_IR : state;
                case STATE.EXIT1_IR:
                    return tms ? STATE.UPDATE_IR : STATE.PAUSE_IR;
                case STATE.PAUSE_IR:
                    return tms ? STATE.EXIT2_IR : state;
                case STATE.EXIT2_IR:
                    return tms ? STATE.UPDATE_IR : STATE.SHIFT_IR;
                case STATE.UPDATE_IR:
                    return tms ? STATE.SELECT_DR_SCAN : STATE.RUN_TEST_IDLE;
                default:
                    throw new Exception("Illegal TAP controller state detected");
            }
        }

Ответы [ 2 ]

1 голос
/ 03 апреля 2020

Я решил проблему так:

class States_path
{
    public enum States
    {
        RESET,
        IDLE,
        DRSELECT,
        DRCAPTURE,
        DRSHIFT,
        DRPAUSE,
        DREXIT1,
        DREXIT2,
        DRUPDATE,
        IRSELECT,
        IRCAPTURE,
        IRSHIFT,
        IRPAUSE,
        IREXIT1,
        IREXIT2,
        IRUPDATE
    }

    private States NextState(States current_states, bool tms)
    {
        switch (current_states)
        {
            case States.RESET:
                return tms ? States.RESET : States.IDLE;
            case States.IDLE:
                return tms ? States.DRSELECT : current_states;
            case States.DRSELECT:
                return tms ? States.IRSELECT : States.DRCAPTURE;
            case States.IRSELECT:
                return tms ? States.RESET : States.IRCAPTURE;
            case States.DRCAPTURE:
                return tms ? States.DREXIT1 : States.DRSHIFT;
            case States.DRSHIFT:
                return tms ? States.DREXIT1 : current_states;
            case States.DREXIT1:
                return tms ? States.DRUPDATE : States.DRPAUSE;
            case States.DRPAUSE:
                return tms ? States.DREXIT2 : current_states;
            case States.DREXIT2:
                return tms ? States.DRUPDATE : States.DRSHIFT;
            case States.DRUPDATE:
                return tms ? States.DRSELECT : States.IDLE;
            case States.IRCAPTURE:
                return tms ? States.IREXIT1 : States.IRSHIFT;
            case States.IRSHIFT:
                return tms ? States.IREXIT1 : current_states;
            case States.IREXIT1:
                return tms ? States.IRUPDATE : States.IRPAUSE;
            case States.IRPAUSE:
                return tms ? States.IREXIT2 : current_states;
            case States.IREXIT2:
                return tms ? States.IRUPDATE : States.IRSHIFT;
            case States.IRUPDATE:
                return tms ? States.DRSELECT : States.IDLE;
            default:
                throw new Exception("Illegal state detected!");
        }
    }

    private bool[] statePath(States current, States end_state)
    {
        return StatePathRecurse(current, end_state, 0);
    }

    private bool[] StatePathRecurse(States current, States end_state,int recursions)
    {
        // Function must not recurse over the entire diagram
        if(++ recursions == Enum.GetNames(typeof(States)).Length)
        {
            // Send error in form of empty bool[]
            return new bool[0];
        }

        bool[] path_false = CheckNextState(false);
        bool[] path_true = CheckNextState(true);

        // Which path to return? 
        // No matter what, the arrays must be larger than 0 before we can return it.
        // In case both arrays are filled, we must find wich is shorter
        if((path_false.Length > 0) && (path_true.Length > 0))
        {
            // Find the shortest path
            return (path_false.Length > path_true.Length) ? path_true : path_false;

        }

        // In case only one of the arrays are filled
        else
        {
            return path_false;
        }


        bool[] CheckNextState(bool tms)
        {
            States next = NextState(current, tms);

            if (next == end_state)
            {
                // Search done, return the correct bool
                return new bool[1] { tms };
            }

            else if (next == current)
            {
                // Looping in the a stable state - this is an error. 
                return new bool[0];
            }

            else
            {
                // Not done with the search - keep recursing

                bool[] cont = StatePathRecurse(next, end_state, recursions);

                if (cont.Length == 0)
                {
                    // Error! Array must have a length
                    return cont;
                }

                else
                {
                    // Array ok - send back
                    bool[] result = new bool[1 + cont.Length];

                    // Adding the last recieved tms to result
                    result[0] = tms;

                    // Combining the recursive bool[] cont to the result
                    cont.CopyTo(result, 1);

                    return result;
                }
            }
        }
    }


}
0 голосов
/ 02 апреля 2020

Ваш вопрос мне не понятен, но, глядя на ваш код, я вижу, что у вас проблемы.

Вам лучше воспринимать это как иерархический конечный автомат.

Пути сканирования DR и ИК-сканирования - это две версии одного и того же конечного автомата.

Работа с обоими в одном операторе switch будет слишком громоздкой, и вы скоро потеряете в ней навигацию.

С помощью иерархического автомата вы можете получить файл верхнего уровня, который переключается между состояниями теста - Сброс теста, Тест на холостом ходу и Выполнение теста.

При полиморфизме состояние «Выполнить тест» будет относиться либо к функциям состояния сканирования DR или IR Scan.

Ваше сканирование DR и IR Каждый код сканирования находится в своем собственном исходном файле.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...