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

时间:2011-10-29 00:26:23

标签: 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;

所以,请记住,我对Java很新。我做了很多基于网络的编程(ruby,php,javascript等)。

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

我的问题是组织的入门。我假设我需要一个“位”类。该类将存储该位是设置为TRUE还是FALSE,位的类型,相关的等式,该位的处理器等等。

然而,我可以达到数百或数千个“位”实例的程度。那我怎么组织这些比特呢?如果我想抓住所有来自某个处理器的实例,我怎么能实现呢?

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

我最初的想法是保留对象的数组或哈希值,并尝试以某种方式保持它们的组织。

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

1 个答案:

答案 0 :(得分:3)

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

例如:

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

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

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

当然,棘手的部分将是解析它,但在这个有限的空间中显示有点困难。至于以图形方式表示这个,您可以构建一些采用该程序并通过操作数计算操作数并以某种方式将其呈现给屏幕的内容。可以毫不费力地构建一个调试器。只需要解析器可以创建的更多信息(操作数映射的行号将有所帮助)。