/// <summary> /// Generate the mosfet instance /// </summary> /// <param name="type">Type</param> /// <param name="name">Name</param> /// <param name="parameters">Parameters</param> /// <param name="netlist">Netlist</param> /// <returns></returns> protected override ICircuitObject Generate(string type, CircuitIdentifier name, List <Token> parameters, Netlist netlist) { // Errors switch (parameters.Count) { case 0: throw new ParseException($"Node expected for component {name}"); case 1: case 2: case 3: throw new ParseException(parameters[parameters.Count - 1], "Node expected", false); case 4: throw new ParseException(parameters[3], "Model name expected"); } // Get the model and generate a component for it ICircuitObject model = netlist.Path.FindModel <ICircuitObject>(netlist.Circuit.Objects, new CircuitIdentifier(parameters[4].image)); ICircuitComponent mosfet = null; if (Mosfets.ContainsKey(model.GetType())) { mosfet = Mosfets[model.GetType()].Invoke(name, model); } else { throw new ParseException(parameters[4], "Invalid model"); } // The rest is all just parameters mosfet.ReadNodes(netlist.Path, parameters); netlist.ReadParameters((IParameterized)mosfet, parameters, 4); return(mosfet); }
/// <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) { // Apply the change to the circuit CircuitIdentifier id; if (netlist.Path.InstancePath != null) { id = netlist.Path.InstancePath.Grow(st.Name.image); } else { id = new CircuitIdentifier(st.Name.image); } ICircuitObject result = Generate(type, id, st.Parameters, netlist); Generated = result; if (result != null) { // Add the circuit component netlist.Circuit.Objects.Add(result); return(true); } else { return(false); } }
/// <summary> /// Deal with a component /// </summary> /// <param name="c">The circuit object</param> private void CheckObject(ICircuitObject c) { // Circuit components if (c is ICircuitComponent icc) { // Check for short-circuited components int n = -1; bool sc = true; for (int i = 0; i < icc.PinCount; i++) { if (n < 0) { n = icc.GetNodeIndex(i); } else if (n != icc.GetNodeIndex(i)) { sc = false; break; } } if (sc) { throw new CircuitException($"{icc.Name}: All pins have been short-circuited"); } // Get the node indices for each pin int[] nodes = new int[icc.PinCount]; for (int i = 0; i < nodes.Length; i++) { nodes[i] = icc.GetNodeIndex(i); unconnected.Add(nodes[i]); } // Use attributes for checking properties var attributes = c.GetType().GetCustomAttributes(false); bool hasconnections = false; foreach (var attr in attributes) { // Voltage driven nodes are checked for voltage loops if (attr is VoltageDriver vd) { voltagedriven.Add(new Tuple <ICircuitComponent, int, int>(icc, nodes[vd.Positive], nodes[vd.Negative])); } // At least one source needs to be available if (attr is IndependentSource) { HasSource = true; } if (attr is ConnectedPins conn) { int[] tmp = new int[conn.Pins.Length]; for (int i = 0; i < conn.Pins.Length; i++) { tmp[i] = nodes[conn.Pins[i]]; } AddConnections(tmp); hasconnections = true; } } // Check connections if (!hasconnections) { AddConnections(nodes); } } }
/// <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); }