private void GenerateSpice(DesignEntity de, Tonka.SPICEModel spiceObj) { var ancestor = de.Parent; while (ancestor != null) { if (ComponentNodeMap.ContainsKey(ancestor)) { return; } ancestor = ancestor.Parent; } var nodes = circuit_obj.nodes; var spiceType = GetSpiceType(de); if (Grounds.Any(spiceType.Item2.Contains)) // is a ground node skip it { return; } var node = new Spice.Node(); node.name = de.Name; node.type = spiceType.Item1; node.classType = spiceType.Item2; // error checking if (node.type == (char)0) { CodeGenerator.Logger.WriteWarning("Missing Spice Type for component {0}", de.Name); } if (node.type == 'X' && node.classType == "") { CodeGenerator.Logger.WriteWarning("Missing Subcircuit Type for component {0}, should be X.<subckt-type>", de.Name); } if (node.classType != "" && !circuit_obj.subcircuits.ContainsKey(node.classType)) { circuit_obj.subcircuits.Add(node.classType, de.SpiceLib); } foreach (var par in spiceObj.Children.SPICEModelParameterCollection) { if (node.parameters.ContainsKey(par.Name)) { CodeGenerator.Logger.WriteError("Duplicate Parameter: {0}: in Component <a href=\"mga:{2}\">{1}</a>", par.Name, de.Name, de.Impl.ID); } else { node.parameters.Add(par.Name, FindTestBenchParameter(par) ?? par.Attributes.Value.Replace("$", "$$")); } } nodes.Add(node); ComponentNodeMap[de] = node; }
public override void visit(Port obj) { CodeGenerator.Logger.WriteDebug( "SpiceVisitor::visit({0}, dest connections: {1})", obj.Name, obj.DstConnections.Count); if (!ComponentNodeMap.ContainsKey(obj.Parent)) // parent is a ground node { return; } var parentNode = ComponentNodeMap[obj.Parent]; // parent node var siginfo_parent = this.siginfo_obj; if (ObjectSiginfoMap.ContainsKey(obj.Parent)) { siginfo_parent = ObjectSiginfoMap[obj.Parent] as Spice.SignalContainer; } int index = 0; try { index = obj.Impl.Attributes.SPICEPortNumber; if (index >= 0 && parentNode.nets.ContainsKey(index)) { CodeGenerator.Logger.WriteError("Duplicate SPICE Port Number: {0}: for Port <a href=\"mga:{2}\">{1}</a>", index, obj.Name, obj.Impl.ID); return; } } catch (System.FormatException ex) { index = -1; // missing index CodeGenerator.Logger.WriteWarning("Invalid SPICE Port Number: {0}: for Port: <a href=\"mga:{2}\">{1}</a>", obj.Impl.Attributes.SPICEPortNumber, obj.Name, obj.Impl.ID); } if (PortNetMap.ContainsKey(obj))// port already mapped to a net object - no need to visit further { if (index >= 0) parentNode.nets.Add(index, PortNetMap[obj]); // spice signal info var siginfo_obj = new Spice.Signal() { name = obj.Name, gmeid = obj.Impl.ID, spicePort = obj.Impl.Attributes.SPICEPortNumber, net = PortNetMap[obj] }; siginfo_parent.signals.Add(siginfo_obj); return; } // create a new net, string net_obj = string.Format("{0}", ++netCount); if (!parentNode.nets.ContainsKey(index)) { if (index >= 0) parentNode.nets.Add(index, net_obj); // spice signal info var siginfo_obj = new Spice.Signal() { name = obj.Name, gmeid = obj.Impl.ID, spicePort = obj.Impl.Attributes.SPICEPortNumber, net = net_obj }; siginfo_parent.signals.Add(siginfo_obj); } else { CodeGenerator.Logger.WriteWarning("Invalid SpiceOrder attribute for schematic port: <a href=\"mga:{0}\">{1}</a>", obj.Impl.ID, obj.Name); } // if we are in the signal integrity mode and the port has an associated parsed trace if (mode == CodeGenerator.Mode.SPICE_SI && CodeGenerator.signalIntegrityLayout.portTraceMap.ContainsKey(obj)) { var trace = CodeGenerator.signalIntegrityLayout.portTraceMap[obj]; if (SigIntegrityTraces.Contains(trace.name)) { CodeGenerator.Logger.WriteInfo("Generating Trace Subcircuit for {0} on Port {1}.{2}", trace.name, obj.Parent.Name, obj.Name); // insert a subckt to model a trace var traceNode = new Spice.Node(); traceNode.name = trace.name; traceNode.type = 'X'; traceNode.classType = string.Format("Trace_{0}", trace.name); traceNode.nets.Add(0, net_obj); // create a new net to replace the original net and carry that wire further net_obj = string.Format("{0}", ++netCount); traceNode.nets.Add(1, net_obj); circuit_obj.nodes.Add(traceNode); // generate the subckt GenerateTraceSubckt(trace); } } else if (CodeGenerator.verbose) CodeGenerator.Logger.WriteWarning("Port {0} has no Trace", obj.Impl.Path); // assign to all connected ports - some nets may not have any connection visit(obj, net_obj); }
public override void visit(Component obj) { CodeGenerator.Logger.WriteDebug( "SpiceVisitor::visit({0})", obj.Name); // create a signal container for this component var siginfo_obj = new Spice.SignalContainer() { name = obj.Name, gmeid = obj.Impl.ID }; ObjectSiginfoMap.Add(obj, siginfo_obj); var siginfo_parent = this.siginfo_obj; if (obj.Parent != null && ObjectSiginfoMap.ContainsKey(obj.Parent)) { siginfo_parent = ObjectSiginfoMap[obj.Parent] as Spice.SignalContainer; } siginfo_parent.signals.Add(siginfo_obj); var nodes = circuit_obj.nodes; var spiceObj = obj.Impl.Children.SPICEModelCollection.FirstOrDefault(); if (spiceObj == null) // no spice model in this component, skip from generating { return; } var spiceType = GetSpiceType(obj); if (Grounds.Any(spiceType.Item2.Contains)) // is a ground node skip it { return; } var node = new Spice.Node(); node.name = obj.Name; node.type = spiceType.Item1; node.classType = spiceType.Item2; // error checking if (node.type == (char)0) { CodeGenerator.Logger.WriteWarning("Missing Spice Type for component {0}", obj.Name); } if (node.type == 'X' && node.classType == "") { CodeGenerator.Logger.WriteWarning("Missing Subcircuit Type for component {0}, should be X.<subckt-type>", obj.Name); } if (node.classType != "" && !circuit_obj.subcircuits.ContainsKey(node.classType)) { circuit_obj.subcircuits.Add(node.classType, obj.SpiceLib); } foreach (var par in spiceObj.Children.SPICEModelParameterCollection) { if (node.parameters.ContainsKey(par.Name)) { CodeGenerator.Logger.WriteError("Duplicate Parameter: {0}: in Component <a href=\"mga:{2}\">{1}</a>", par.Name, obj.Name, obj.Impl.ID); } else { node.parameters.Add(par.Name, par.Attributes.Value); } } nodes.Add(node); ComponentNodeMap[obj] = node; }
public override void visit(Port obj) { CodeGenerator.Logger.WriteDebug( "SpiceVisitor::visit({0}, dest connections: {1})", obj.Name, obj.DstConnections.Count); if (!ComponentNodeMap.ContainsKey(obj.Parent)) // parent is a ground node { return; } var parentNode = ComponentNodeMap[obj.Parent]; // parent node var siginfo_parent = this.siginfo_obj; if (ObjectSiginfoMap.ContainsKey(obj.Parent)) { siginfo_parent = ObjectSiginfoMap[obj.Parent] as Spice.SignalContainer; } int index = 0; try { index = obj.Impl.Attributes.SPICEPortNumber; if (index >= 0 && parentNode.nets.ContainsKey(index)) { CodeGenerator.Logger.WriteError("Duplicate SPICE Port Number: {0}: for Port <a href=\"mga:{2}\">{1}</a>", index, obj.Name, obj.Impl.ID); return; } } catch (System.FormatException ex) { index = -1; // missing index CodeGenerator.Logger.WriteWarning("Invalid SPICE Port Number: {0}: for Port: <a href=\"mga:{2}\">{1}</a>", obj.Impl.Attributes.SPICEPortNumber, obj.Name, obj.Impl.ID); } if (PortNetMap.ContainsKey(obj))// port already mapped to a net object - no need to visit further { if (index >= 0) { parentNode.nets.Add(index, PortNetMap[obj]); } // spice signal info var siginfo_obj = new Spice.Signal() { name = obj.Name, gmeid = obj.Impl.ID, spicePort = obj.Impl.Attributes.SPICEPortNumber, net = PortNetMap[obj] }; siginfo_parent.signals.Add(siginfo_obj); return; } // create a new net, string net_obj = string.Format("{0}", ++netCount); if (!parentNode.nets.ContainsKey(index)) { if (index >= 0) { parentNode.nets.Add(index, net_obj); } // spice signal info var siginfo_obj = new Spice.Signal() { name = obj.Name, gmeid = obj.Impl.ID, spicePort = obj.Impl.Attributes.SPICEPortNumber, net = net_obj }; siginfo_parent.signals.Add(siginfo_obj); AddNetToSiginfoTraceability(obj, net_obj); } else { CodeGenerator.Logger.WriteWarning("Invalid SpiceOrder attribute for schematic port: <a href=\"mga:{0}\">{1}</a>", obj.Impl.ID, obj.Name); } // if we are in the signal integrity mode and the port has an associated parsed trace if (mode == CodeGenerator.Mode.SPICE_SI && CodeGenerator.signalIntegrityLayout.portTraceMap.ContainsKey(obj)) { var trace = CodeGenerator.signalIntegrityLayout.portTraceMap[obj]; if (SigIntegrityTraces.Contains(trace.name)) { CodeGenerator.Logger.WriteInfo("Generating Trace Subcircuit for {0} on Port {1}.{2}", trace.name, obj.Parent.Name, obj.Name); // insert a subckt to model a trace var traceNode = new Spice.Node(); traceNode.name = trace.name; traceNode.type = 'X'; traceNode.classType = string.Format("Trace_{0}", trace.name); traceNode.nets.Add(0, net_obj); // create a new net to replace the original net and carry that wire further net_obj = string.Format("{0}", ++netCount); traceNode.nets.Add(1, net_obj); circuit_obj.nodes.Add(traceNode); // generate the subckt GenerateTraceSubckt(trace); } } else if (CodeGenerator.verbose) { CodeGenerator.Logger.WriteWarning("Port {0} has no Trace", obj.Impl.Path); } // assign to all connected ports - some nets may not have any connection visit(obj, net_obj); }