/// <summary> /// Read nodes for a component /// </summary> /// <param name="c">The circuit component</param> /// <param name="parameters">The parameters</param> /// <param name="index">The index where to start reading, defaults to 0</param> public static void ReadNodes(this ICircuitComponent c, SubcircuitPath path, List <Token> parameters, int index = 0) { int count = c.PinCount; // Check that there are enough parameters left to read if (parameters.Count < index + count) { if (parameters.Count > 0) { throw new ParseException(parameters[parameters.Count - 1], $"{count} nodes expected"); } throw new ParseException($"Unexpected end of line, {count} nodes expected"); } // Extract the nodes CircuitIdentifier[] nodes = new CircuitIdentifier[count]; for (int i = index; i < index + count; i++) { if (IsNode(parameters[i])) { // Map to a new node if necessary, else make the node local to the current path CircuitIdentifier node = new CircuitIdentifier(parameters[i].image); if (path.NodeMap.TryGetValue(node, out CircuitIdentifier mapped)) { node = mapped; } else if (path.InstancePath != null) { node = path.InstancePath.Grow(node); } // Store the node nodes[i] = node; } else { throw new ParseException(parameters[i], "Node expected"); } } // Succeeded c.Connect(nodes); }
/// <summary> /// Read subcircuit definitions /// </summary> /// <param name="name">Name</param> /// <param name="parameters">Parameters</param> /// <param name="netlist">Netlist</param> /// <returns></returns> public override bool Read(string type, Statement st, Netlist netlist) { if (st.Parameters.Count < 2) { throw new ParseException(st.Name, "Subcircuit name expected", false); } // Create the identifier of the subcircuit definition CircuitIdentifier name = new CircuitIdentifier(st.Parameters[0].image); if (netlist.Path.DefinitionPath != null) { name = netlist.Path.DefinitionPath.Grow(name); } // Extract the subcircuit definition statements StatementsToken body = (StatementsToken)st.Parameters[st.Parameters.Count - 1]; SubcircuitDefinition definition = new SubcircuitDefinition(name, body); // Parse nodes and parameters bool mode = true; // true = nodes, false = parameters for (int i = 1; i < st.Parameters.Count - 1; i++) { if (mode) { // After this, only parameters will follow if (st.Parameters[i].image.ToLower() == "params:") { mode = false; } // Parameters have started, so we will keep reading parameters else if (st.Parameters[i].kind == ASSIGNMENT) { mode = false; AssignmentToken at = st.Parameters[i] as AssignmentToken; definition.Defaults.Add(new CircuitIdentifier(at.Name.image), at.Value); } // Still reading nodes else if (ReaderExtension.IsNode(st.Parameters[i])) { definition.Pins.Add(new CircuitIdentifier(st.Parameters[i].image)); } } else if (st.Parameters[i].kind == ASSIGNMENT) { AssignmentToken at = st.Parameters[i] as AssignmentToken; definition.Defaults.Add(new CircuitIdentifier(at.Name.image), at.Value); } } // Create a new subcircuit path SubcircuitPath orig = netlist.Path; netlist.Path = new SubcircuitPath(orig, definition); foreach (var s in definition.Body.Statements(StatementType.Subcircuit)) { netlist.Readers.Read(s, netlist); } // Restore netlist.Path = orig; // Return values netlist.Definitions.Add(definition.Name, definition); Generated = definition; return(true); }
/// <summary> /// Read /// </summary> /// <param name="type">Type</param> /// <param name="st">Statement</param> /// <param name="netlist">Netlist</param> /// <returns></returns> public override bool Read(string type, Statement st, Netlist netlist) { // Initialize List <CircuitIdentifier> instancepins = new List <CircuitIdentifier>(); Dictionary <CircuitIdentifier, Token> instanceparameters = new Dictionary <CircuitIdentifier, Token>(); CircuitIdentifier definition = null; // Get the name CircuitIdentifier name; if (netlist.Path.InstancePath != null) { name = netlist.Path.InstancePath.Grow(st.Name.image); } else { name = new CircuitIdentifier(st.Name.image); } // Format: <NAME> <NODES>* <SUBCKT> <PAR1>=<VAL1> ... // Or: <NAME> <NODES>* <SUBCKT> params: <PAR1>=<VAL1> ... bool mode = true; // true = nodes, false = parameters for (int i = 0; i < st.Parameters.Count; i++) { // Reading nodes if (mode) { if (ReaderExtension.IsNode(st.Parameters[i])) { instancepins.Add(definition = new CircuitIdentifier(st.Parameters[i].image)); } else { instancepins.RemoveAt(instancepins.Count - 1); mode = false; } } // Reading parameters // Don't use ELSE! We still need to read the last parameter if (!mode) { if (st.Parameters[i].kind == ASSIGNMENT) { AssignmentToken at = st.Parameters[i] as AssignmentToken; switch (at.Name.kind) { case WORD: case IDENTIFIER: instanceparameters.Add(new CircuitIdentifier(at.Name.image), at.Value); break; default: throw new ParseException(at.Name, "Parameter name expected"); } } } } // If there are only node-like tokens, then the last one is the definition by default if (mode) { instancepins.RemoveAt(instancepins.Count - 1); } // Modify the instancepins to be local or use the nodemap for (int i = 0; i < instancepins.Count; i++) { if (netlist.Path.NodeMap.TryGetValue(instancepins[i], out CircuitIdentifier node)) { instancepins[i] = node; } else if (netlist.Path.InstancePath != null) { instancepins[i] = netlist.Path.InstancePath.Grow(instancepins[i].Name); } } // Find the subcircuit definition if (netlist.Path.DefinitionPath != null) { definition = netlist.Path.DefinitionPath.Grow(definition); } SubcircuitDefinition subcktdef = netlist.Path.FindDefinition(netlist.Definitions, definition) ?? throw new ParseException(st.Parameters[st.Parameters.Count - 1], "Cannot find subcircuit definition"); Subcircuit subckt = new Subcircuit(subcktdef, name, instancepins, instanceparameters); SubcircuitPath orig = netlist.Path; netlist.Path = new SubcircuitPath(netlist, orig, subckt); // Read all control statements foreach (var s in subcktdef.Body.Statements(StatementType.Control)) { netlist.Readers.Read(s, netlist); } // Read all model statements foreach (var s in subcktdef.Body.Statements(StatementType.Model)) { netlist.Readers.Read(s, netlist); } // Read all component statements foreach (var s in subcktdef.Body.Statements(StatementType.Component)) { netlist.Readers.Read(s, netlist); } // Restore netlist.Path = orig; Generated = subckt; return(true); }