mobile-eda/lib/domain/services/netlist_generator.dart

388 lines
11 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 网表生成器模块
*
* 从原理图连接关系提取电气网表
* 支持网络命名/自动命名
* 输出 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 = <String>[];
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 = <String>[];
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<String, dynamic> generateJsonNetlist(Design design) {
final nets = <String, Map<String, dynamic>>{};
for (final net in design.nets.values) {
final connections = <Map<String, dynamic>>[];
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 = <String>{};
// 收集已使用的网络名
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<Net> extractNetsFromConnections(Design design) {
final nets = <Net>[];
final connectionMap = <String, List<ConnectionPoint>>{};
// 收集所有连接点
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<String> 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<String> 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 [],
});
}