组织简单的布尔逻辑模拟器 - Java

Rya*_*anB 5 java

在我的工作中,我们将带有布尔逻辑程序的处理器用于工业应用。这些程序可能会变得非常冗长和复杂。它们基本上由一组输入位、输出位和内部布尔位组成。这些位随后用于产生输出的逻辑语句中。输入和输出可以是物理线输出或串行通信,但这并不重要。

这是一个快速、简化的示例:

Inputs:
input1, input2, input3;

Outputs:
output1, output2, output3;

Boolean:
bool1, bool2, bool3;

Logic:
assign input1 && input2 to bool1;
assign input1 && bool1 to output1;
assign input2 && input3 to bool2;
assign output1 && bool2 to output2;
assign output1 && output2 || bool2 to bool3;
Run Code Online (Sandbox Code Playgroud)

所以,请记住,我对 Java 很陌生。我已经完成了相当多的基于网络的编程(ruby、php、javascript 等)。

基本上我希望模拟器做的是分解程序的格式并允许图形模拟。程序可以相互通信,因此模拟器也应该能够处理多个程序(并将 I/O 连接在一起)。

我的问题是开始组织。我假设我需要有一个“位”类。此类将存储该位是设置为 TRUE 还是 FALSE、位的类型、相关等式、该位来自哪个处理器等。

但是,我可以达到拥有数百或数千个“位”实例的地步。那么我如何组织这些位呢?例如,如果我想获取来自某个处理器的所有实例,我该如何实现?

此外,当我更改模拟器中输入位的状态(TRUE 或 FALSE)时,它将更新其他几个位的状态。对此有何建议?我想让它尽可能灵活,因为我想添加额外的功能。例如,某些位可以被指定为定时器(当它们的条件满足时,它们可能需要一定的时间来设置,或者当它们的条件不再满足时,它们可能需要一定的时间退出)。

我最初的想法是保留对象的数组或散列,并尝试以某种方式使它们组织起来。

我基本上是在寻找任何建议。提前致谢。

chu*_*ubs 4

有趣的问题。您基本上是在构建一个简单的布尔值虚拟处理器。所以我会将模拟器构建为一个处理器。因此,本质上您将拥有寄存器(输入、输出或内部寄存器),然后逻辑将定义您的操作数。由于您只处理布尔逻辑,因此很容易想出一组您需要的操作数:AND、OR、NOT、XOR。对于像&&、||这样的东西 这些操作数将有两个输入和一个输出。但是,对于 NOT,您将只有一个输入和一个输出。因此,我会为您想要支持的每个操作数创建一个类。所有操作数都扩展/实现抽象类或接口。这将为客户端提供接口,以相同的方式评估每个操作数并执行程序。

例如:

public class AndOperation implements Operand, Argument {

    private Argument argument1;
    private Argument argument2;
    private String output;

    public AndOperation( Argument arg1, Argument arg2 ) {
       this( arg1, arg2, null ); // this is for chaining where no output exists.
    }

    public AndOperation( Argument arg1, Argument arg2, String output ) {
       this.argument1 = arg1;
       this.argument2 = arg2;
       this.output = output;
    }

    public boolean evaluate() {
       return argument1.evaluate() && argument2.evaluate();
    }

    public String getOutputRegister() {
       return output;
    }
}

public interface Argument {
    public boolean evaluate();
}

public class Register implements Argument {
    private String name;
    private boolean value;

    public boolean evaluate() {
       return value;
    }

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


public class Program implements Iterable<Operand> {

   public Map<Register> registers;
   public List<Operand> operands;

   public void parse( InputStream stream ) {
      // this will take in a stream, parse it, and create the 
      // program.  Create the registers, and operands used 
      // to evaluate the program
   }

   public void evaluate() {
      for( Operand op : operands ) {
         evaluate( op );
      }
   }

   public void evaluate( Operand operand ) {
         boolean output = op.evaluate();
         String name = op.getOutputRegister();
         Register register = registers.get( name );
         register.setValue( output );
   }          

   public Iterator<Operand> iterator() {
      return new Debugger( this );
   }
}

public class Debugger implements Iterator<Operand> {
   private Program program;
   private int line = 0;

   public boolean hasNext() {
      return line < program.size();
   }

   public Operand next() {
      Operand operand = program.getOperands().get( line );
      program.evaluate( operand );
      line++;
      return operand;
   }
}
Run Code Online (Sandbox Code Playgroud)

大概就是这样。然而,我想指出的一件事是如何透明地将多个操作数链接在一起。操作数并不关心它是从寄存器还是另一个操作数读取输入。由于寄存器和操作数实现了参数,因此它可以替代其中任何一个。例如:

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

当然,棘手的部分是解析它,但在有限的空间内展示它有点困难。就以图形方式表示这一点而言,您可以构建一些东西来获取该程序并逐个操作数评估它并以某种方式将其呈现到屏幕上。无需付出太多努力就可以基于此构建调试器。只需要您的解析器可以创建的更多信息(行号到操作数映射会很有帮助)。