作业集4~6 总结性博客:数字电路仿真器的迭代开发

一、前言

相比于上一次作业,此次作业由于专业术语较多,所需要的专业知识更多,做起来比较吃力。但此三次作业延续了上一次的逐步深入,将第四次作业写出来之后,后面写起来更加得心应手。此次作业围绕围绕“数字电路仿真器”这一主题进行了三轮迭代开发。三次作业逐步深入,从基础组合逻辑仿真,到多输出元件与信号处理,再到支持子电路嵌套的层次化设计,覆盖了面向对象编程、解析器设计、信号传播算法等多个知识点。

作业集 主要知识点
7-1 NCHUD-数字电路模拟程序-1 面向对象编程(类、对象、方法封装)
正则表达式(PatternMatcher
集合框架(MapList,含 LinkedHashMapHashMapArrayList
迭代算法与标志位控制(while(changed) 信号传播)
多路分支与逻辑运算(switch-case
静态方法与静态初始化块
Scanner 标准输入读取
Comparator 与 Lambda 表达式排序
字符串解析(splitsubstring
6个核心类
7-1 NCHUD-数字电路模拟程序-2  

与作业4基本一致,并增加:
多输出引脚的管理与特殊格式化(如译码器索引、分配器信号串)
无效/未连接信号的统一处理(返回 -1 列表)
按元件类型与编号的稳定排序实现

 6个核心类
7-1 NCHUD-数字电路模拟程序-4  

抽象类、继承与多态(Component 抽象类及其子类)
枚举类型(PinType、GateType)
自定义异常(CircuitException)
递归下降解析(子电路定义 C1:…endc 与嵌套实例化)
组合模式(SubCircuitComponent 内部组合 Circuit,形成树形结构)
方法重写(computeOutput())
集合框架(LinkedHashMap、HashMap、ArrayList)
字符串匹配与正则(String.matches、split)
递归遍历与数据收集(collectOutputs)
字符串与数字提取(extractNumber)

 12个类/接口

二、设计与分析

2-1 NCHUD-数字电路模拟程序-1

核心类:

  1. Gate 
  2. Circuit 
  3. Simulator 
  4. Parser 
  5. Reporter 
  6. Main 程序入口

 

类间关系:

51ee006e83a5339042adb385331453db

复杂度分析:

f372c808b2d7aa045d6233661cd7df84

心得:

作业 4 的核心实现思路为构建计算图模型,并通过迭代更新的方式完成组合逻辑求解。仿真器中基于while(changed)的迭代循环能够适配任意器件互连拓扑,但存在两处明显缺陷:一是执行效率较低;二是不具备组合环路检测能力,电路中若存在组合环路,会引发死循环或输出逻辑错误。

2-2 NCHUD-数字电路模拟程序-2

核心类:(与作业四基本相同,但在Reporter 和 Gate 的部分方法中增强了对多输出元件(译码器、数据分配器)的格式化支持。)

  1. Gate (compute()M 型译码器使能条件修正(S1=1,S2=0,S3=0)
  2. Circuit 
  3. Simulator 
  4. Parser 
  5. Reporter (1)prepareOutput() 中针对 M 型译码器输出格式化为 名字:索引(输出低电平有效通道的索引);

          (2)针对 F 型数据分配器输出格式化为 名字:--0- 形式的信号串(有效位为实际值,无效位为 -)

  6. Main 程序入口

类间关系:

3a4ae54f5584e9c0f5b861e88516413f

复杂度分析:

a09bc417b1b6a27f78c8e66f306351b4

心得:

该实现虽可保证功能运行无误,但 Gate 类职责划分不合理,承载了大量引脚初始化相关逻辑。各类器件的控制引脚数量、输入输出引脚排布均在initPins()方法内通过 switch 分支硬编码实现,后续新增器件类型时,会持续膨胀该方法,造成类结构臃肿、维护成本上升。

优化方案可引入工厂模式或策略模式解耦引脚初始化逻辑;但结合作业 5 工程体量,当前简化实现方案具备可行性,可予以保留。

失误:

在书写过程中,由于某些格式问题,在基础元件测验中有问题。

2-3 NCHUD-数字电路模拟程序-4

核心类:

  1. Pin 
  2. Component(抽象类) 
  3. AndGate / OrGate / NotGate / XorGate / XnorGate 具体组合逻辑门,实现 computeOutput()
  4. SubCircuitComponent 
  5. Circuit 
  6. Connection 
  7. Parser 
  8. CircuitException 
  9. Main 程序入口,读取输入,调用 Parser 构建顶层电路并仿真输出

类间关系:

c41db0436053134b5c4eac171968e046

复杂度分析:

d80c5ec16a6a9b05a597696060d246a8

心得:

层次化架构设计赋予电路模型极高的拓展与复用灵活性,但同时提升了调试排查成本。跨层级的信号互连映射需依托SubCircuitComponent.evaluate()手动完成,机制等效于硬件描述语言中的模块端口绑定逻辑。
本次课程实践充分体现,规范合理的数据结构、分层清晰的解析执行流程,是搭建复杂电路仿真系统的核心基础。

失误:

此次作业中,难度增加,沿用之前的类时,会有些答案格式错误,或者输出案例错误。

三、问题

作业四:搭建门级仿真器
1.Gate.compute() 方法体积膨胀,难以扩展
所有门电路的逻辑均集中在一个 compute() 方法内,通过大型 switch 语句区分类型。当需要添加新器件时,必须直接修改该方法,导致其规模不断增大,且容易在改动时引入错误。这种设计不符合“对扩展开放、对修改封闭”的原则。可为每种门创建独立子类,各自封装计算逻辑。

2.迭代仿真算法可能因组合环路而无法终止

Simulator 使用 while (changed) 循环反复计算所有门,直至没有输出发生变化。这种方法在遇到组合环路(如两个非门首尾相连)时,信号会持续翻转,循环永远无法退出,导致程序卡死。解决思路包括设置最大迭代次数上限,或采用拓扑排序一次性计算,既能提高效率,也能检测环路。

3. 输入引脚多驱动冲突时缺乏报错机制
记录驱动关系时使用了 putIfAbsent,该操作在输入引脚已被驱动时会静默忽略后续连接。如果同一输入不慎被多个输出驱动,冲突不会被提示,仿真结果却可能错误,增加了调试难度。

作业五:增强多输出元件支持
1. Reporter 中输出格式逻辑混杂,可读性差
译码器需要输出 名字:索引,数据分配器需要输出 名字:--0- 形式的信号串,普通门则是 引脚:值。这些格式化逻辑全部集中在 Reporter 类中,导致方法内出现大量 if (type == 'M') 等类型判断,结构混乱。可改为每种元件添加自描述的输出格式化方法,由元件自身负责生成字符串,Reporter 仅负责排序与调用。

2.多输出门中无效信号 -1 的传播不完整

单输出门在输入未知时只需返回一个 -1,但多输出门(如 F 型数据分配器)在控制信号无效时,必须将所有输出都置为 -1。初期实现仅将出错通道置为无效,其余输出保留了默认值,导致仿真结果部分正确,不易察觉。在设计 invalidM() 和 invalidF() 方法时,需确保返回列表长度与输出引脚总数一致,且每个元素均为 -1。

作业六:实现层次化子电路仿真
1. 子电路定义顺序与引用顺序不一致
解析输入时,可能在子电路 C1 的定义内部引用了尚未定义的子电路 C2(因为 C2 的定义写在后面),导致解析失败。解决方法是采用两遍解析:第一遍扫描所有 C1: … endc 块,创建子电路对象并注册;第二遍再解析各子电路内部的连接关系。这样无论定义顺序如何,引用时对象均已存在。

2. 子电路输入输出引脚方向混淆
SubCircuitComponent 的外部引脚有输入、输出之分,内部子电路的引脚同样有 INPUT/OUTPUT 方向。在连接时容易将方向弄反,例如将外部输入误判为可驱动其他引脚的源,导致信号传递错误。通过在纸上绘制接口对应关系可帮助理清思路。规范做法是为 Pin 设置 INPUT/OUTPUT 枚举,连接时强制检查源引脚必须是 OUTPUT,目标引脚必须是 INPUT,否则抛出异常。

3.异常信息过于简略,不利于调试

当连接格式或元件定义出现错误时,程序仅抛出 CircuitException("Unexpected line: ..."),没有提供出错行号或具体原因。改进方法是在异常信息中附加上下文,如当前行号、冲突引脚名称或元件类型,从而大幅提升问题定位效率。

 

四、总结

通过作业四至作业六的迭代开发,我从零构建了一个支持层次化子电路的数字电路仿真器。三次作业难度递进、功能逐步扩展,从平坦门级仿真到多输出元件增强,最终实现支持子电路定义的层次化系统,完整覆盖了面向对象设计、解析器构建与仿真算法等核心编程能力。

  1. 作业四建立了基本的门级仿真模型,采用迭代算法求解组合逻辑,涉及正则解析、集合框架与基本类结构设计。作业五在作业四基础上增强了对译码器、数据分配器等多输出元件的支持,重点修正了使能条件与输出格式化逻辑。作业六引入子电路定义与实例化,通过递归下降解析和组合模式实现了树形层次结构的信号传播。整个过程中运用的核心知识点包括:抽象类、继承与多态,正则表达式匹配,集合框架(Map、List)的使用,以及递归下降解析与组合模式的应用。
  2. 开发过程中遇到的主要问题包括:单一方法体积膨胀导致扩展困难,引脚编号硬编码偏移量降低了灵活性,迭代仿真可能在组合环路中陷入死循环,多驱动冲突被静默忽略导致调试困难,使能条件写反造成译码器始终不工作,多输出门无效信号传播不完整,子电路定义顺序与引用顺序不一致,输入输出引脚方向混淆,外部输入未同步至子电路内部,以及异常信息过于简略。针对这些问题的改进方向有:为每种门建立独立子类遵循开闭原则,采用拓扑排序替代迭代循环以提升效率并检测环路,引入工厂模式或策略模式增强可扩展性,在冲突发生时抛出明确异常,以及完善错误信息包含行号和具体原因。

通过这三次作业的实践,不仅加深了对面向对象原则中封装、继承与多态的理解,也切身体会到解析器设计、信号传播算法和层次化建模在实际工程中的重要性与复杂度。

 

posted @ 2026-06-24 22:40  ALKQ  阅读(1)  评论(0)    收藏  举报