【问题标题】:Boolean Logic Simulator - StackOverflowError布尔逻辑模拟器 - StackOverflowError
【发布时间】:2011-12-22 22:35:56
【问题描述】:

我正在创建一个布尔逻辑模拟器。我发布了一个关于应用程序的组织和一般设置的问题,它位于:Organizing Simple Boolean Logic Simulator - Java。我认为这并不直接适用于其他问题,因此可以单独发布。请原谅我的代码,我对 Java 很陌生。

代码的组织实际上很简单,但是当我尝试在assign语句中将变量分配给自身时遇到了问题。

例如,我们通常会使用这样的语句:

assign input1 * input2 + test3 * input2 to test3;

当 input1 和 input2 为高电平时,test3 将变为高电平。那时, input1 可能会退出,而 test3 仍然很高,因为它在语句中引用了自己。 (注意:* => AND,+ => OR)正如您在下面看到的,当变量在其分配语句中引用自身时,我遇到了问题,就像上面一样。那是因为当我尝试获取上面语句的值时,我得到了:

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

等等。它只是试图一遍又一遍地评估它的陈述。

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();
    }

}

Parser 类:我只包含了其中的一部分,因为实际的解析并不是那么相关。 请注意,当我将变量分配给自身时,会产生错误。 在下面的第二个测试中,我将 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 )

希望这已经足够清楚了。如果对问题是什么或我正在尝试做什么有任何疑问,请告诉我。提前致谢。

【问题讨论】:

    标签: java logic boolean stack-overflow simulator


    【解决方案1】:

    假设这是一个模拟器/评估器(而不是方程求解器),那么您需要将系统建模为随时间变化的状态。因此,声明:

    assign test1 * input1 to test1;
    

    表示test1t+1的状态为test1t * input1t

    您的代码所做的是不区分 test1t 和 test1t+1 ...因此导致无限递归。

    一种解决方案是将状态(变量的值)与方程分开表示,并使用不同的数据结构来表示时间t和时间t + 1的状态。

    【讨论】:

    • 在您的模拟中有时 t 和 t + 1 ......当然。 OTOH,如果这个逻辑模拟器没有考虑时间(或者至少有“之前”和“之后”状态),那么像assign test1 * input1 to test1 这样的输入是错误的。
    【解决方案2】:

    您描述的是电路中的反馈回路。它们在现实中确实存在,在较低的层次上它们被使用,例如对于内存元件(触发器和锁存器),在更高级别上,您可以将其用于具有确实需要反馈的操作的电路(例如 IIR 滤波器)。

    在这个更高级别的“应用程序”中,您在不同(逻辑)操作之间有寄存器。 这就是你如何让循环进入你的逻辑。然后,您必须将结果计算为时间的函数。

    您从使用复位值(通常为 0)循环的寄存器/输入的内容开始。然后开始计算。您可以在中间的寄存器处中断循环,并通过您的分配语句从前一个周期的值计算一个周期的值。这也意味着即使输入没有变化,输出也会随着时间步的变化而变化。对于每个输出,您还拥有一个输出值,而不是一个输出序列(随时间变化)。

    另一个选项(我建议您使用简单的模拟器)是禁止此类循环并在您识别它们时抛出错误消息。

    如果这是用于生产,我只能建议:不要再次发明轮子。这不是一个新问题。有例如那里有硬件描述语言(例如 Verilog 或 VHDL),其中存在几个模拟器(例如,来自 synopsys 的 vcs 或如果你想要一个免费的 verilator)。

    【讨论】:

    • 感谢您的意见。它并不是真正用于生产,我希望只是将它用作工作中的工具。我们将处理器用于特定的工业应用,一旦我把所有东西都整理好,我想拥有一些特定的功能。现在,为了将其翻译成 Java,我正在考虑为每个位关联一个“使用位置”哈希。这样,当一个位状态发生变化时,可以重新评估它的“使用位置”位,看看它们是否发生了变化,等等。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-11
    • 1970-01-01
    • 1970-01-01
    • 2017-01-04
    • 1970-01-01
    • 2015-04-18
    相关资源
    最近更新 更多