/** * 网表生成器模块 * * 从原理图连接关系提取电气网表 * 支持网络命名/自动命名 * 输出 SPICE 格式网表 * * @version 0.1.0 * @date 2026-03-07 */ import '../models/core_models.dart'; /// 网表生成器 class NetlistGenerator { /// 生成 SPICE 格式网表 /// /// [design] 设计数据 /// [options] 生成选项 /// /// 返回 SPICE 网表字符串 String generateSpiceNetlist(Design design, {SpiceOptions? options}) { options ??= const SpiceOptions(); final buffer = StringBuffer(); // 1. 文件头 buffer.writeln('* ${design.name}'); buffer.writeln('* Generated by Mobile EDA'); buffer.writeln('* Date: ${DateTime.now().toIso8601String()}'); buffer.writeln('* Version: ${design.version}'); buffer.writeln(); // 2. 包含模型文件(如果有) if (options.includeModelFiles.isNotEmpty) { for (final modelFile in options.includeModelFiles) { buffer.writeln('.INCLUDE "$modelFile"'); } buffer.writeln(); } // 3. 生成元件实例 buffer.writeln('* Components'); for (final component in design.components.values) { buffer.writeln(_generateSpiceComponent(component, design)); } buffer.writeln(); // 4. 生成网络连接 buffer.writeln('* Nets'); for (final net in design.nets.values) { buffer.writeln(_generateSpiceNet(net)); } buffer.writeln(); // 5. 生成模型定义(如果有自定义模型) if (options.generateModelDefinitions) { buffer.writeln('* Models'); for (final component in design.components.values) { final modelDef = _generateSpiceModel(component); if (modelDef != null) { buffer.writeln(modelDef); } } buffer.writeln(); } // 6. 分析命令 buffer.writeln('* Analysis'); if (options.analysisType == 'dc') { buffer.writeln('.DC ${options.dcSourceName} ${options.dcStart} ${options.dcStop} ${options.dcStep}'); } else if (options.analysisType == 'ac') { buffer.writeln('.AC ${options.acType} ${options.acPoints} ${options.acStartFreq} ${options.acStopFreq}'); } else if (options.analysisType == 'tran') { buffer.writeln('.TRAN ${options.transientStep} ${options.transientStop}'); } // 7. 输出控制 if (options.printVariables.isNotEmpty) { buffer.writeln('.PRINT ${options.printVariables.join(" ")}'); } // 8. 文件尾 buffer.writeln('.END'); return buffer.toString(); } /// 生成 SPICE 元件行 String _generateSpiceComponent(Component component, Design design) { final prefix = _getSpicePrefix(component.type); final name = '$prefix${component.name}'; // 获取引脚连接 final connections = []; for (final pin in component.pins) { // 查找引脚所属的网络 String netName = '0'; // 默认为地 for (final net in design.nets.values) { for (final conn in net.connections) { if (conn.componentId == component.id && conn.pinId == pin.pinId) { netName = net.name; break; } } if (netName != '0') break; } connections.add(netName); } // 获取元件值 final value = component.value ?? _getDefaultValue(component.type); // 构建 SPICE 行 // 格式:Xname node1 node2 ... model [value] final parts = [name, ...connections]; if (component.type == ComponentType.ic || component.type == ComponentType.transistor) { // IC 和晶体管需要模型名 final modelName = component.partNumber ?? component.name; parts.add(modelName); } parts.add(value); return parts.join(' '); } /// 生成 SPICE 网络定义 String _generateSpiceNet(Net net) { // SPICE 中网络通过元件连接隐式定义,这里生成注释 final connections = []; for (final conn in net.connections) { if (conn.componentId != null && conn.pinId != null) { connections.add('${conn.componentId}:${conn.pinId}'); } } return '* Net ${net.name}: ${connections.join(", ")}'; } /// 生成 SPICE 模型定义 String? _generateSpiceModel(Component component) { if (component.type == ComponentType.resistor) { return null; // 电阻不需要模型定义 } else if (component.type == ComponentType.capacitor) { return null; // 电容不需要模型定义 } else if (component.type == ComponentType.inductor) { return null; // 电感不需要模型定义 } else if (component.type == ComponentType.diode) { return '.MODEL ${component.partNumber ?? component.name} D()'; } else if (component.type == ComponentType.transistor) { // 简化处理,实际需要更多信息 return '.MODEL ${component.partNumber ?? component.name} NPN()'; } else if (component.type == ComponentType.ic) { // IC 需要子电路定义,这里简化处理 return null; } return null; } /// 获取 SPICE 元件前缀 String _getSpicePrefix(ComponentType type) { switch (type) { case ComponentType.resistor: return 'R'; case ComponentType.capacitor: return 'C'; case ComponentType.inductor: return 'L'; case ComponentType.diode: return 'D'; case ComponentType.transistor: return 'Q'; case ComponentType.ic: return 'X'; case ComponentType.connector: return 'J'; case ComponentType.custom: return 'X'; } } /// 获取默认元件值 String _getDefaultValue(ComponentType type) { switch (type) { case ComponentType.resistor: return '1k'; case ComponentType.capacitor: return '1u'; case ComponentType.inductor: return '1m'; case ComponentType.diode: return '1N4148'; case ComponentType.transistor: return '2N2222'; case ComponentType.ic: return ''; case ComponentType.connector: return ''; case ComponentType.custom: return ''; } } /// 生成网络表(JSON 格式) Map generateJsonNetlist(Design design) { final nets = >{}; for (final net in design.nets.values) { final connections = >[]; for (final conn in net.connections) { connections.add({ 'type': conn.type.name, if (conn.componentId != null) 'componentId': conn.componentId, if (conn.pinId != null) 'pinId': conn.pinId, if (conn.position != null) 'position': { 'x': conn.position!.x, 'y': conn.position!.y, }, if (conn.layerId != null) 'layerId': conn.layerId, }); } nets[net.id] = { 'name': net.name, 'type': net.type.name, 'connections': connections, if (net.voltage != null) 'voltage': net.voltage, if (net.isDifferential) 'isDifferential': true, if (net.differentialPair != null) 'differentialPair': net.differentialPair, if (net.busName != null) 'busName': net.busName, }; } return { 'designId': design.id, 'designName': design.name, 'version': design.version, 'generatedAt': DateTime.now().toIso8601String(), 'componentCount': design.components.length, 'netCount': design.nets.length, 'nets': nets, }; } /// 自动命名网络 /// /// 为未命名的网络生成唯一名称 void autoRenameNets(Design design) { var netCounter = 1; final usedNames = {}; // 收集已使用的网络名 for (final net in design.nets.values) { usedNames.add(net.name); } // 为未命名的网络生成名称 for (final net in design.nets.values) { if (net.name.startsWith('N') || net.name.isEmpty) { String newName; do { newName = 'N$netCounter'; netCounter++; } while (usedNames.contains(newName)); usedNames.add(newName); // 更新网络名(实际应用中需要更新设计数据) // net.name = newName; } } } /// 从连接关系提取网络 /// /// 分析元件引脚连接,自动生成网络 List extractNetsFromConnections(Design design) { final nets = []; final connectionMap = >{}; // 收集所有连接点 for (final trace in design.traces.values) { // 走线连接的两个端点 if (trace.points.length >= 2) { final startConn = ConnectionPoint( id: '${trace.id}_start', type: ConnectionType.wireEnd, position: trace.points.first, layerId: trace.layerId, ); final endConn = ConnectionPoint( id: '${trace.id}_end', type: ConnectionType.wireEnd, position: trace.points.last, layerId: trace.layerId, ); final netId = trace.netId; connectionMap.putIfAbsent(netId, () => []).add(startConn); connectionMap.putIfAbsent(netId, () => []).add(endConn); } } // 创建网络对象 final timestamp = DateTime.now().millisecondsSinceEpoch; for (final entry in connectionMap.entries) { nets.add(Net( id: entry.key, name: 'N${entry.key.substring(0, 8)}', // 简化命名 type: NetType.signal, connections: entry.value, metadata: Metadata( createdAt: timestamp, updatedAt: timestamp, ), )); } return nets; } } /// SPICE 生成选项 class SpiceOptions { /// 包含的模型文件路径 final List includeModelFiles; /// 是否生成模型定义 final bool generateModelDefinitions; /// 分析类型:'dc', 'ac', 'tran' final String analysisType; /// DC 分析电源名 final String dcSourceName; /// DC 分析起始值 final double dcStart; /// DC 分析结束值 final double dcStop; /// DC 分析步长 final double dcStep; /// AC 分析类型:'LIN', 'DEC', 'OCT' final String acType; /// AC 分析点数 final int acPoints; /// AC 分析起始频率 final double acStartFreq; /// AC 分析结束频率 final double acStopFreq; /// 瞬态分析步长 final double transientStep; /// 瞬态分析停止时间 final double transientStop; /// 要打印的变量 final List printVariables; const SpiceOptions({ this.includeModelFiles = const [], this.generateModelDefinitions = false, this.analysisType = 'dc', this.dcSourceName = 'V1', this.dcStart = 0.0, this.dcStop = 5.0, this.dcStep = 0.1, this.acType = 'DEC', this.acPoints = 10, this.acStartFreq = 1.0, this.acStopFreq = 1e6, this.transientStep = 1e-6, this.transientStop = 1e-3, this.printVariables = const [], }); }