【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") } }
测试结果:
模拟电路的半加器