繁体   English   中英

Swift 中的 16 位逻辑/计算机模拟

[英]16 bit logic/computer simulation in Swift

我正在尝试使用 Swift 对 16 位计算机进行基本模拟。 计算机将具有

  • 一个 ALU
  • 2个寄存器

就这样。 我有足够的知识来直观地创建这些部件并理解它们是如何工作的,但是在使用我目前的方法时,用更多的输入来制作更大的组件变得越来越困难。

我目前的方法是将每个组件包装在一个struct中。 这在早期很有效,但是在坚持计算机科学原理的同时管理多个输入变得越来越困难。

主要问题是组件没有随时钟信号更新。 当在 output 变量 c 上调用get时,我有组件更新的c 然而,这忽略了时钟信号的概念,并且可能会在以后引起进一步的问题。

也很难为每个变量创建 getter 和 setter,而不会出现关于可变性的错误。 尽管我已经解决了这些错误,但它们很烦人并且减慢了开发过程。

最后一个大问题是更新 output。 当输入改变时,output 不会更新; 当被告知这样做时,它会更新。 这与真实计算机的质量不准确,是一个基本错误。

这是一个例子。 就是我前面提到的ALU。 它需要两个 16 位输入和 16 位输出。 它有两个一元 ALU,可以将 16 位数字设为零、取反或两者兼而有之。 最后,它根据f标志添加或进行位明智的比较,如果选择no标志,则反转 output。

struct ALU {
    //Operations are done in the order listed. For example, if zx and nx are 1, it first makes input 1 zero and then inverts it.
    var x : [Int] //Input 1
    var y : [Int] //Input 2
    var zx : Int //Make input 1 zero
    var zy : Int //Make input 2 zero
    var nx : Int //Invert input 1
    var ny : Int //Invert input 2
    var f : Int //If 0, do a bitwise AND operation. If 1, add the inputs
    var no : Int //Invert the output
    public var c : [Int] { //Output
        get {
            //Numbers first go through unary ALUs. These can negate the input (and output the value), return 0, or return the inverse of 0. They then undergo the operation specified by f, either addition or a bitwise and operation, and are negated if n is 1.
            var ux = UnaryALU(z: zx, n: nx, x: x).c //Unary ALU. See comments for more
            var uy = UnaryALU(z: zy, n: ny, x: y).c 
            var fd = select16(s: f, d1: Add16(a: ux, b: uy).c, d0: and16(a: ux, b: uy).c).c //Adds a 16 bit number or does a bitwise and operation. For more on select16, see the line below.
            var out = select16(s: no, d1: not16(a: fd).c, d0: fd).c //Selects a number. If s is 1, it returns d1. If s is 0, it returns d0. d0 is the value returned by fd, while d1 is the inverse.
            return out
        }
    }
    public init(x:[Int],y:[Int],zx:Int,zy:Int,nx:Int,ny:Int,f:Int,no:Int) {
        self.x = x
        self.y = y
        self.zx = zx
        self.zy = zy
        self.nx = nx
        self.ny = ny
        self.f = f
        self.no = no
    }
}

我将c用于 output 变量,将多位值存储在Int arrays 中,并将单个位存储在Int值中。

我在第 6 代 iPad 上使用 Swift 5.0 在 Swift Playgrounds 3.0 上执行此操作。 我将每个组件或组件集存储在模块中的单独文件中,这就是为什么某些变量和所有structs都标记为public的原因。 我将不胜感激任何帮助。 提前致谢。

所以,我已经完全重做我的方法,并找到了绕过我所面临问题的方法。 我所做的是为每个输入制作我称之为“跟踪器变量”的东西。 当为每个变量调用get时,它返回分配给它的跟踪器的值。 调用set时,它会调用update() function 来更新电路的 output。 它还会更新跟踪器的值。 这实质上创建了每个变量的“副本”。 我这样做是为了防止任何无限循环。

不幸的是,这里需要跟踪器。 我会证明为什么

var variable : Type {
    get {
        return variable //Calls the getter again, resulting in an infinite loop
    }
    set {
        //Do something
    }
}

为了制作 setter,Swift 还需要制作 getter。 在此示例中,调用variable只是再次调用get ,导致对get的调用永无止境。 跟踪器变量是一种使用最少额外代码的解决方法。

使用更新方法可确保 output 响应任何输入的变化。 由于组件本身的架构,这也适用于时钟信号。 尽管它看起来像时钟一样,但实际上并非如此。

例如,在数据触发器中,时钟信号被传递到门。 时钟信号所做的只是在信号关闭时停用组件。 所以,我可以在update()中实现它,同时保持对现实的忠诚。

这是一个半加器的例子。 请注意,我提到的跟踪器变量在其名称前用下划线标记。 它有两个输入xy ,每个输入 1 位。 它还有两个输出, highlow ,也称为进位和求和。 输出也是一位。

struct halfAdder {
    private var _x : Bool //Tracker for x
    public var x: Bool { //Input 1
        get {
            return _x //Return the tracker’s value
        }
        set {
            _x = x //Set the tracker to x
            update() //Update the output
        }
    }
    private var _y : Bool //Tracker for y
    public var y: Bool { //Input 2
        get {
            return _y
        }
        set {
            _y = y
            update()
        }
    }
    public var high : Bool //High output, or ‘carry’
    public var low : Bool //Low output, or ‘sum’
    internal mutating func update(){ //Updates the output
        high = x && y //AND gate, sets the high output
        low = (x || y) && !(x && y) //XOR gate, sets the low output
    }
    public init(x:Bool, y:Bool){ //Initializer
        self.high = false //This will change when the variables are set, ensuring a correct output. 
        self.low = false //See above
        self._x = x //Setting trackers and variables
        self._y = y
        self.x = x
        self.y = y
    }
}

这是一个非常干净的方式,除了跟踪器,完成这个任务。 通过使用Bool的 arrays 而不是单个值,可以轻松地将其扩展为适合任意数量的位。 它尊重时钟信号,在输入变化时更新 output,与真实计算机非常相似。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM