/*---------------------------------------------------------------------------------------- SPICE Output of EAGLE Schematics with ULP ============================================ Load schematic name.sch and run ULP with RUN spice The SPICE netlist will be named name.cir. The ULP generates for each part one line in the netlist. Lines starting with "*" are comment. Example Resistor: R1 3 4 1Kohm | |_| | | | |_ Component value or model name (for complex components). | | The value is defined with the VALUE command of EAGLE. | | Must meet SPICE naming conventions! | | | |_ Node numbers between which the component is placed (they are equivalent to | EAGLE nets in the schematic). The ULP transfers the net names to node numbers. | Node 0 is always the reference node (ground); it is defined by the net GND | in the schematic. Node numbers with a leading "-" character (e.g. -3) describe | open pins - that is, the nets do not exist. | |_ Reference f. component category (in this case R for resistor). Is defined with PREFIX in the EAGLE device. R1 is the complete component name defined in the EAGLE schematic. For SPICE, only R is relevant. The name must meet the SPICE conventions! Example AND Gate: U1 AND(2) $G_DPWR $G_DGND 3 -1 4 T_GATE_AND IO_STD ;7400 | |____________________| |____| |_______________| |___|__ EAGLE Value | | | | (after ";" = comment) | | | | | | | |_ If instead of the value a more complex | | | string is needed, this string is to be | | | defined in the symbol( e.g. in layer SPICE). | | | Here: "spicepostf T_GATE_AND IO_STD" | | | | | |_ Node numbers: The order must meet the demands of | | the related SPICE model. It is equivalent to the | | sort order (R1 before R10..) of the EAGLE pin names. | | The order can be changed with the text: | | "spiceorder Pinname1 Pinname2 Pinname3 .." | | defined in the EAGLE-Symbol. | | If less pins are specified in this text than the | | symbol contains, nodes are generated only for those | | pins. | | | |_ Some components need an additional string between name and node | numbers. It is defined as text in the EAGLE symbol. Here: | "spicepref AND(2) $G_DPWR $G_DGND" | |_ Component name according to SPICE conventions. "U" is defined as Prefix in the EAGLE device. If SPICE needs a name different from the EAGLE component name, the string "spicename X" can be placed in the EAGLE SPICE layer. "X" represents a valid SPICE name and is preceeding the EAGLE component name. Example: EAGLE name: "IC1", string in layer SPICE: "spicename XAND", Spice-Name: "XANDIC1". SPICE Strings ============= The string in the layer SPICE should be small enough (size) not to extend the area used by all the other objects of the EAGLE symbol, as the area is used in various operations, even if the SPICE layer is not displayed. Restrictions ============ Supply symbols (except GND) are ignored, as well as "gates" containing at least one pin with Direction "Sup". Voltage sources are to be defined as a device. Instruments etc. ================ Not only real components but also instruments, voltage sources, etc. can be defined as EAGLE devices. These components must contain dummy packages and must not contain pins with Direction "Sup". Power Pins of Components ======================== If such pins are defined as an individual EAGLE "gate", they appear in the SPICE netlist only if they have been expicitly placed in the schematic with the INVOKE command. The naming of those "gates" however will lead to problems at the moment, as for instance the name of the power gate belonging to component U1 will be U1xx (if the gate name is xx). ----------------------------------------------------------------------------------------*/ /* Generate PSPICE netlist from EAGLE schematic */ string InsName = "", PinName = "", PinOrder, PinSignals, SpiceName = "spicename", SpicePref = "spicepref", SpicePostf = "spicepostf", SpiceOrder = "spiceorder", BeforeName, BeforeNodes, AfterNodes, NodeOrder, Nodes[]; int n, i, PinsNoNet, t, NrOfPins, NrOfPinDefs, PinOrderDefined; string SignalOnPin (string InsName, string PinName) { string SigName = ""; schematic (Sch) { Sch.nets(N){ N.pinrefs(PR) { if (InsName == PR.instance.name) if (PinName == PR.pin.name) SigName = N.name; } }; return SigName; } } string GetItemTillEnd(string s) { // check error handling yet int i = 0; while ((!isspace(s[i])) && (strlen(s) >= i)) i++; // skip first word while ((isspace(s[i])) && (strlen(s) >= i)) i++; // skip blanks s = strsub(s, i, strlen(s)-i); return s; } string GetNextItem(string s) { // and stip NodeOrder int i = 0; string item = ""; if (strlen(s)) { while (isspace(s[i])) { i++; // skip first word NodeOrder = strsub(NodeOrder, 1 , strlen(NodeOrder)-1); } while (isgraph(s[i])) { item = item + s[i]; NodeOrder = strsub(NodeOrder, 1 , strlen(NodeOrder)-1); i++; }; }; return item; } void OutputPart(UL_PART PRT) { int IsSupplySymbol, HasPins, pos; string s; PRT.instances(I) { IsSupplySymbol = 0; HasPins = 0; NrOfPins = 0; NrOfPinDefs = 0; PinOrderDefined = 0; BeforeName = ""; BeforeNodes = ""; AfterNodes = ""; NodeOrder = ""; I.gate.symbol.texts(T) { // get spice strings pos = strstr(strlwr(T.value), SpiceName); if (pos >= 0) { BeforeName = GetItemTillEnd(T.value); } pos = strstr(strlwr(T.value), SpicePref); if (pos >= 0) { BeforeNodes = GetItemTillEnd(T.value); } pos = strstr(strlwr(T.value), SpicePostf); if (pos >= 0) { AfterNodes = GetItemTillEnd(T.value); } pos = strstr(strlwr(T.value), SpiceOrder); if (pos >= 0) { NodeOrder = GetItemTillEnd(T.value); PinOrderDefined = 1; printf("* Pinorder: %s\n", NodeOrder); } } // done get spice strings I.gate.symbol.pins(PIN) { if ((PIN.direction == PIN_DIRECTION_SUP)) IsSupplySymbol = 1; HasPins = 1; } if (HasPins) { printf("\n* %s\n",I.name); if (!IsSupplySymbol) { // output loop for valid instances InsName = I.name; printf("%s%s %s ",BeforeName, I.name, BeforeNodes); I.gate.symbol.pins(PIN) { // Loop through instance pins PinOrder = GetNextItem(NodeOrder); if (PinOrderDefined) PinSignals = SignalOnPin(I.name, PinOrder); else PinSignals = SignalOnPin(I.name, PIN.name); s = PinSignals; if (s !="") { for (i = 0; i <= n; i++) { if ((PinOrder != "") || (!PinOrderDefined)) if (Nodes[i] == s) { printf("%d ", i); NrOfPinDefs++; } }; } else if ((PinOrder != "") || (!PinOrderDefined)) { printf("-%d ", ++PinsNoNet); NrOfPinDefs++; } NrOfPins++; }; printf("%s", AfterNodes); if (AfterNodes != "") printf(" ;"); printf("%s\n", I.value); if (PinOrderDefined && (NrOfPins != NrOfPinDefs)) printf("* Warning: not all of the pins defined!!!\n"); } // done output loop for valid instances else printf("* dropped (assumed supply symbol)!!!\n"); } } } schematic(SCH) { t = time(); output(filename(filesetext(SCH.name, ".CIR"))) { printf("* PSPICE netlist created with\n* %s\n", EAGLE_SIGNATURE); printf("* %s\n*\n*\n", t2string(t)); n = 0; SCH.nets(N) { Nodes[0] = "GND"; if (N.name != "GND") Nodes[++n] = N.name; } printf("* Node Net\n*\n"); for (i = 0; i <= n; i++) printf("* %4d %s\n", i, Nodes[i]); printf("*\n"); PinsNoNet = 0; SCH.sheets(SH){ SH.parts(PRT) OutputPart(PRT); printf(".END\n"); } } }