Симулятор логической логики - StackOverflowError - PullRequest
1 голос
/ 06 ноября 2011

Я создаю симулятор булевой логики. Я опубликовал вопрос об организации и общей настройке приложения, и он находится здесь: Организация Simple Boolean Logic Simulator - Java . Я подумал, что это не относится непосредственно к другому вопросу, поэтому было бы хорошо опубликовать это отдельно. Пожалуйста, извините мой код, я очень плохо знаком с Java.

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

Например, мы обычно будем использовать такие выражения:

assign input1 * input2 + test3 * input2 to test3;

Когда input1 и input2 имеют высокий уровень, test3 станет высоким. В этот момент input1 может выпасть, а test3 все равно будет высоким, поскольку он ссылается на себя в выражении. (Примечание: * => AND, + => OR) Как вы можете видеть ниже, у меня возникают проблемы, когда переменная ссылается на себя в своем операторе assign, как описано выше. Это потому, что когда я пытаюсь получить значение приведенного выше утверждения, я получаю:

input1 * input2 + (input1 * input2 + (input1 * input2 + test3 * input2) * input2) * input2

Etc. Он просто пытается оценить свое утверждение снова и снова.

public interface Argument {
    public boolean evaluate();
}

Вот класс «Бит», который хранит информацию о каждом бите. Бит может быть либо «жестко запрограммированным», либо истинным, либо ложным, либо ему может быть назначен оператор.

public class Bit implements Argument {

    private String name;
    private boolean value;
    private Argument assign;
    private boolean assigned;

    Bit( String name, boolean value ) {
        this.name = name;
        this.value = value;
    }

    @Override
    public boolean evaluate() {
        if ( assigned == true ) {
            return assign.evaluate();
        } else {
            return value;
        }
    }

    public void setValue( boolean value ) {
        this.value = value;
    }

    public void setAssign( Argument assign ) {
        this.assign = assign;
        this.assigned = true;
    }

}

Это пример класса Operation; остальные очень похожи.

public class OrOperation implements Argument {

    private Argument argument1, argument2;

    public OrOperation( Argument arg1, Argument arg2 ) {
        this.argument1 = arg1;
        this.argument2 = arg2;
    }

    @Override
    public boolean evaluate() {
        return argument1.evaluate() || argument2.evaluate();
    }

}

Класс парсера: я включил только часть этого, так как на самом деле синтаксический анализ не так уж важен. Обратите внимание, что когда я присваиваю себе переменную, возникает ошибка. Во втором тесте ниже я назначил test3 для test3. Я могу сделать вывод, что это потому, что test3 пытается определить значение самого себя, вызывая этот второй оператор снова и снова.

public class Parser {

    public HashMap<String, Bit> bits = new HashMap<String, Bit>();

    Parser(String file) {

        bits.put( "test1", new Bit( "test1", true ) );
        bits.put( "test2", new Bit( "test2", true ) );
        bits.put( "test3", new Bit( "test3", false ) );
        bits.put( "test4", new Bit( "test4", true ) );

        // Works great
        bits.get("test3").setAssign( parseStatement("test1 * ~test2 + test4 * test2") );
        System.out.println( bits.get("test3").evaluate() );

        // Produces error
        bits.get("test3").setAssign( parseStatement("test1 * test2 + test3 * test2") );
        System.out.println( bits.get("test3").evaluate() );

    }
}

Синтаксический анализатор в основном создает операторы так: (взято из предыдущего вопроса)

Operand op = new AndOperand( register1, new OrOperand( register2, register3 );
boolean output = op.evaluate(); // this is register1 && (register2 || register3 )

Надеюсь, это было достаточно ясно. Дайте мне знать, если есть какие-либо вопросы относительно того, в чем проблема или что я пытаюсь сделать. Заранее спасибо.

Ответы [ 2 ]

1 голос
/ 06 ноября 2011

То, что вы описываете, является обратной связью в цепи. Они действительно существуют в действительности, на более низком уровне они используются, например. для элементов памяти (триггеры и защелки) на более высоком уровне вы можете использовать его для цепей, в которых есть операции, которые действительно требуют обратной связи (например, фильтр БИХ).

В «приложениях» более высокого уровня есть регистры между различными (логическими) операциями. Вот как вы получаете циклы в вашей логике. Затем вы должны вычислить свои результаты как функцию времени.

Вы начинаете с содержимого регистров / входов, которые зацикливаются со значением сброса (обычно 0). И тогда начните вычисление. Вы можете разорвать цикл в регистрах между ними и вычислить значения для циклов с помощью ваших операторов присваивания из значений предыдущего цикла. Это также означает, что выходной сигнал может меняться от шага к времени, даже если он не изменяется. У вас также есть для каждого выхода не одно выходное значение, а последовательность выходов (меняющихся во времени).

Другой вариант (который я бы посоветовал, поскольку у вас есть простой симулятор) - запретить такие циклы и выдавать сообщение об ошибке при их распознавании.

Если это для производства, я могу только порекомендовать: НЕ снова изобрести колесо. Это не новая проблема. Есть, например, языки описания аппаратного обеспечения (например, Verilog или VHDL), где существует пара симуляторов (например, vcs из synopsys или verilator, если вам нужен бесплатный).

1 голос
/ 06 ноября 2011

Предполагая, что это симулятор / оценщик (а не решатель уравнений), вам необходимо смоделировать систему как состояния, которые меняются со временем. Итак, утверждение:

assign test1 * input1 to test1;

означает, что состояние test1 t + 1 является test1 t * input1 t .

То, что делает ваш код, не делает различий между test1 t и test1 t + 1 ... и в результате вызывает бесконечную рекурсию.

Одним из решений является представление состояния (значений переменных) отдельно от уравнений и, кроме того, использование различных структур данных для представления состояния во время t и состояния во время t + 1.

...