【SCALA】3、模拟电路

Simulation

package demo17

abstract class Simulation {

  type Action = () => Unit
  case class WorkItem(time: Int, action: Action)

  private var curtime = 0

  def currentTime: Int = curtime

  //日程,记录所有未执行的工作项目
  private var agenda: List[WorkItem] = List()

  //更新排序
  private def insert(ag: List[WorkItem], item: WorkItem): List[WorkItem] = {
    //如果头部时间大于当前时间,那么直接头插
    if(ag.isEmpty || item.time < ag.head.time) {
      item :: ag
    } else {
      //否则遍历递归到合适位置
      ag.head :: insert(ag.tail, item)
    }
  }

  //向日程添加工作项,第二个参数是传名参数
  def afterDelay(delay: Int)(block: => Unit) = {
    val item = WorkItem(currentTime + delay, () => block)
    agenda = insert(agenda, item)
  }

  private def next() = {
    (agenda: @unchecked) match {
      case item :: rest =>
        agenda = rest
        curtime = item.time
        //执行这个工作项的操作
        //这里一定要带括号,不然就是相当于get操作
        item.action()
    }
  }

  def run() = {
    //插入方法
    afterDelay(0) {
      println("*** simulation started, time = " + currentTime + " ***")
    }
    //执行所有的操作
    while(!agenda.isEmpty) next()
  }

}

BasicCircuitSimulation

package demo17

abstract class BasicCircuitSimulation extends Simulation {

  //用来做门的延迟
  def InverterDelay: Int
  def AndGateDelay: Int
  def OrGateDelay: Int

  //线
  class Wire {

    private var sigVal = false
    private var actions: List[Action] = List()

    def getSignal = sigVal
    def setSignal(s: Boolean) = {
      if(s != sigVal) {
        sigVal = s
        //这里是对actions每一个元素应用=》_ () 操作也就是f => f(),每次线的状态变化的时候,执行actions
        actions foreach (_ ())
      }
    }

    def addAction(a: Action) = {
      //加入载头部
      actions = a :: actions
      //并执行一次a
      a()
    }
  }

  //非门,也就是翻转器,在uinput和output之间建立饭庄器
  def inverter(input: Wire, output: Wire) = {
    def invertAction() = {
      val inputSig = input.getSignal
      //在制定的延迟之后执行对应的方法
      afterDelay(InverterDelay) {
        //设置输出线信号为input相反
        output setSignal !inputSig
      }
      //test
//      output setSignal !inputSig
    }
    //添加动作到input线
    input addAction invertAction
  }

  //与门,输入两个线信号的&操作
  def andGate(a1: Wire, a2: Wire, output: Wire) = {
    def andAction() = {
      val a1Sig = a1.getSignal
      val a2Sig = a2.getSignal
      afterDelay(AndGateDelay) {
        output setSignal (a1Sig & a2Sig)
      }
      //test
//      output setSignal (a1Sig & a2Sig)
    }
    a1 addAction andAction
    a2 addAction andAction
  }

  def orGate(o1: Wire, o2: Wire, output: Wire) = {
    def orAction() = {
      val o1Sig = o1.getSignal
      val o2Sig = o2.getSignal
      afterDelay(OrGateDelay) {
        output setSignal (o1Sig | o2Sig)
      }
      //test
//      output setSignal (o1Sig | o2Sig)
    }
    o1 addAction orAction
    o2 addAction orAction
  }

  //用来观察线的型号变化
  def probe(name: String, wire: Wire) = {
    def probeAction() = {
      println(name + " " + currentTime + " new-value = " + wire.getSignal)
    }
    wire addAction probeAction
  }


}

CircuitSimulation

package demo17

abstract class CircuitSimulation extends BasicCircuitSimulation {

  def halfAdder(a: Wire, b: Wire, s: Wire, c: Wire) = {
    val d, e = new Wire
    orGate(a, b, d)
    andGate(a, b, c)
    inverter(c, e)
    andGate(d, e, s)
  }

  def fullAdder(a: Wire, b: Wire, cin: Wire, sum: Wire, cout: Wire) = {
    val s, c1, c2 = new Wire
    halfAdder(a, cin, s, c1)
    halfAdder(b, s, sum, c2)
    orGate(c1, c2, cout)
  }

}

MySimulation

package demo17

object MySimulation extends CircuitSimulation {
  def InverterDelay: Int = 1

  def AndGateDelay: Int = 3

  def OrGateDelay: Int = 5

}

测试结果:

package demo17

import demo17.MySimulation._

object Demo18Test {
  def main(args: Array[String]): Unit = {
    val input1, input2, sum, carry = new Wire
    probe("sum", sum)
    probe("carry", carry)
    halfAdder(input1, input2, sum, carry)
    input1 setSignal true
    run()
    input2 setSignal true
    run()
    println("over")
  }
}

测试结果:

模拟电路的半加器

 

原文地址:https://www.cnblogs.com/cutter-point/p/11094272.html