/// <summary> /// Read a transistor model /// </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) { // Errors switch (st.Parameters.Count) { case 0: throw new ParseException(st.Name, "Model name and type expected", false); } // The model depends on the model level, find the model statement int level = 0; string version = null; int lindex = -1, vindex = -1; for (int i = 0; i < st.Parameters.Count; i++) { if (st.Parameters[i].kind == ASSIGNMENT) { AssignmentToken at = st.Parameters[i] as AssignmentToken; if (at.Name.image.ToLower() == "level") { lindex = i; level = (int)Math.Round(netlist.ParseDouble(at.Value)); } if (at.Name.image.ToLower() == "version") { vindex = i; version = at.Value.image.ToLower(); } if (vindex >= 0 && lindex >= 0) { break; } } } if (lindex >= 0) { st.Parameters.RemoveAt(lindex); } if (vindex >= 0) { st.Parameters.RemoveAt(vindex < lindex ? vindex : vindex - 1); } // Generate the model ICircuitObject model = null; if (Levels.ContainsKey(level)) { model = Levels[level].Invoke(new CircuitIdentifier(st.Name.image), type, version); } else { throw new ParseException(st.Name, $"Unknown mosfet model level {level}"); } // Read all the parameters netlist.ReadParameters((IParameterized)model, st.Parameters); // Output netlist.Circuit.Objects.Add(model); Generated = model; 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); }