/// <summary>
        /// Generates a new voltage controlled current source: GName.
        /// </summary>
        /// <param name="name">Name of generated voltage controlled current source.</param>
        /// <param name="parameters">Parameters for current source.</param>
        /// <param name="context">Reading context.</param>
        /// <returns>
        /// A new instance of voltage controlled current source.
        /// </returns>
        protected IEntity GenerateVoltageControlledCurrentSource(string name, ParameterCollection parameters, ICircuitContext context)
        {
            if (parameters.Count == 5 &&
                parameters.IsValueString(0) &&
                parameters.IsValueString(1) &&
                parameters.IsValueString(2) &&
                parameters.IsValueString(3) &&
                parameters.IsValueString(4))
            {
                var vccs = new VoltageControlledCurrentSource(name);
                context.CreateNodes(vccs, parameters);
                context.SetParameter(vccs, "gain", parameters.Get(4));
                return(vccs);
            }
            else
            {
                if (parameters.Count == 3 &&
                    parameters[0] is PointParameter pp1 && pp1.Values.Count() == 2 &&
                    parameters[1] is PointParameter pp2 && pp2.Values.Count() == 2)
                {
                    var vccsNodes = new ParameterCollection(new List <Parameter>());
                    vccsNodes.Add(pp1.Values.Items[0]);
                    vccsNodes.Add(pp1.Values.Items[1]);
                    vccsNodes.Add(pp2.Values.Items[0]);
                    vccsNodes.Add(pp2.Values.Items[1]);

                    var vccs = new VoltageControlledCurrentSource(name);
                    context.CreateNodes(vccs, vccsNodes);
                    context.SetParameter(vccs, "gain", parameters.Get(2));
                    return(vccs);
                }
        public override IEntity Generate(
            string componentIdentifier,
            string originalName,
            string type,
            ParameterCollection parameters,
            ICircuitContext context)
        {
            if (parameters.Any(p => p is AssignmentParameter asgParameter && asgParameter.Name.ToLower() == "v"))
            {
                var entity = new BehavioralVoltageSource(componentIdentifier);
                context.CreateNodes(entity, parameters);

                var expressionParameter = (AssignmentParameter)parameters.First(p => p is AssignmentParameter asgParameter && asgParameter.Name.ToLower() == "v");
                entity.Parameters.Expression  = expressionParameter.Value;
                entity.Parameters.ParseAction = (expression) =>
                {
                    var parser = new ExpressionParser(context.Evaluator.GetEvaluationContext(null), false, context.CaseSensitivity);
                    return(parser.Resolve(expression));
                };
                return(entity);
            }

            if (parameters.Any(p => p is AssignmentParameter asgParameter && asgParameter.Name.ToLower() == "i"))
            {
                var entity = new BehavioralCurrentSource(componentIdentifier);
                context.CreateNodes(entity, parameters);

                var expressionParameter = (AssignmentParameter)parameters.First(p =>
                                                                                p is AssignmentParameter asgParameter && asgParameter.Name.ToLower() == "i");

                entity.Parameters.Expression  = expressionParameter.Value;
                entity.Parameters.ParseAction = (expression) =>
                {
                    var parser = new ExpressionParser(context.Evaluator.GetEvaluationContext(null), false, context.CaseSensitivity);
                    return(parser.Resolve(expression));
                };
                return(entity);
            }

            return(null);
        }
        public override SpiceSharp.Components.Component Generate(
            string componentIdentifier,
            string originalName,
            string type,
            ParameterCollection parameters,
            ICircuitContext context)
        {
            if (parameters.Any(p => p is AssignmentParameter asgParameter && asgParameter.Name.ToLower() == "v"))
            {
                var entity = new BehavioralVoltageSource(componentIdentifier);
                context.CreateNodes(entity, parameters);

                var expressionParameter = (AssignmentParameter)parameters.First(p => p is AssignmentParameter asgParameter && asgParameter.Name.ToLower() == "v");
                var baseParameters      = entity.ParameterSets.Get <SpiceSharpBehavioral.Components.BehavioralBehaviors.BaseParameters>();
                baseParameters.Expression = expressionParameter.Value;
                baseParameters.Parser     = (sim) => CreateParser(context, sim);
                return(entity);
            }

            if (parameters.Any(p => p is AssignmentParameter asgParameter && asgParameter.Name.ToLower() == "i"))
            {
                var entity = new BehavioralCurrentSource(componentIdentifier);
                context.CreateNodes(entity, parameters);

                var expressionParameter = (AssignmentParameter)parameters.First(p =>
                                                                                p is AssignmentParameter asgParameter && asgParameter.Name.ToLower() == "i");

                var baseParameters = entity.ParameterSets.Get <SpiceSharpBehavioral.Components.BehavioralBehaviors.BaseParameters>();
                baseParameters.Expression = expressionParameter.Value;
                baseParameters.Parser     = (sim) => CreateParser(context, sim);

                return(entity);
            }

            return(null);
        }
        /// <summary>
        /// Reads <see cref="Control"/> statement and modifies the context.
        /// </summary>
        /// <param name="statement">A statement to process.</param>
        /// <param name="context">A context to modify.</param>
        public override void Read(Control statement, ICircuitContext context)
        {
            if (statement.Parameters.Count != 2)
            {
                context.Result.Validation.Add(new ValidationEntry(ValidationEntrySource.Reader, ValidationEntryLevel.Warning, "Wrong parameter count for .CONNECT", statement.LineInfo));
                return;
            }

            string nodeA = statement.Parameters.Get(0).Image;
            string nodeB = statement.Parameters.Get(1).Image;

            var vs = new VoltageSource($"Voltage connector: {nodeA} <-> {nodeB}");

            context.CreateNodes(vs, statement.Parameters);
            context.Result.AddEntity(vs);
        }
        /// <summary>
        /// Generates a new inductor.
        /// </summary>
        /// <param name="name">Name of inductor to generate.</param>
        /// <param name="parameters">Parameters and pins for inductor.</param>
        /// <param name="context">Reading context.</param>
        /// <returns>
        /// A new instance of inductor.
        /// </returns>
        protected SpiceSharp.Components.Component GenerateInd(string name, ParameterCollection parameters, ICircuitContext context)
        {
            if (parameters.Count != 3)
            {
                context.Result.Validation.Add(new ValidationEntry(ValidationEntrySource.Reader,
                                                                  ValidationEntryLevel.Warning,
                                                                  $"Inductor expects 3 parameters/pins", parameters.LineInfo));
                return(null);
            }

            var inductor = new Inductor(name);

            context.CreateNodes(inductor, parameters);
            context.SetParameter(inductor, "inductance", parameters.Get(2));

            return(inductor);
        }
        public override SpiceSharp.Components.Component Generate(string name, string originalName, string type, ParameterCollection parameters, ICircuitContext context)
        {
            var losslessLine = new LosslessTransmissionLine(name);

            context.CreateNodes(losslessLine, parameters);

            parameters = parameters.Skip(4);

            foreach (Parameter parameter in parameters)
            {
                if (parameter is AssignmentParameter ap)
                {
                    var paramName = ap.Name.ToLower();

                    if (paramName == "z0" || paramName == "zo")
                    {
                        context.SetParameter(losslessLine, "z0", ap.Value);
                    }
                    else if (paramName == "f")
                    {
                        context.SetParameter(losslessLine, "f", ap.Value);
                    }
                    else if (paramName == "td")
                    {
                        context.SetParameter(losslessLine, "td", ap.Value);
                    }
                    else if (paramName == "reltol")
                    {
                        context.SetParameter(losslessLine, "reltol", ap.Value);
                    }
                    else if (paramName == "abstol")
                    {
                        context.SetParameter(losslessLine, "abstol", ap.Value);
                    }
                    else
                    {
                        context.Result.Validation.Add(new ValidationEntry(ValidationEntrySource.Reader, ValidationEntryLevel.Warning, $"Invalid parameter: {parameter.Image}", parameter.LineInfo));
                    }
                }
            }

            return(losslessLine);
        }
 /// <summary>
 /// Generates a new current controlled current source: FName.
 /// </summary>
 /// <param name="name">Name of generated current controlled current source.</param>
 /// <param name="parameters">Parameters for current source.</param>
 /// <param name="context">Reading context.</param>
 /// <returns>
 /// A new instance of current controlled current source.
 /// </returns>
 protected IEntity GenerateCurrentControlledCurrentSource(string name, ParameterCollection parameters, ICircuitContext context)
 {
     if (parameters.Count == 4 &&
         parameters.IsValueString(0) &&
         parameters.IsValueString(1) &&
         parameters.IsValueString(2) && parameters[2].Image.ToLower() != "value" &&
         parameters.IsValueString(3))
     {
         var cccs = new CurrentControlledCurrentSource(name);
         context.CreateNodes(cccs, parameters);
         cccs.ControllingSource = context.NameGenerator.GenerateObjectName(parameters.Get(2).Image);
         context.SetParameter(cccs, "gain", parameters.Get(3));
         return(cccs);
     }
     else
     {
         return(CreateCustomCurrentSource(name, parameters, context, false));
     }
 }
        public override IEntity Generate(string name, string originalName, string type, ParameterCollection parameters, ICircuitContext context)
        {
            if (parameters.Count > 7 || parameters.Count < 5)
            {
                context.Result.Validation.Add(new ValidationEntry(ValidationEntrySource.Reader, ValidationEntryLevel.Warning, "Wrong parameter count for voltage delay", parameters.LineInfo));
                return(null);
            }

            var vd = new VoltageDelay(name);

            context.CreateNodes(vd, parameters);

            parameters = parameters.Skip(4);

            foreach (Parameter parameter in parameters)
            {
                if (parameter is AssignmentParameter ap)
                {
                    var paramName = ap.Name.ToLower();

                    if (paramName == "reltol")
                    {
                        context.SetParameter(vd, "reltol", ap.Value);
                    }
                    else if (paramName == "abstol")
                    {
                        context.SetParameter(vd, "abstol", ap.Value);
                    }
                    else
                    {
                        context.Result.Validation.Add(new ValidationEntry(ValidationEntrySource.Reader, ValidationEntryLevel.Warning, $"Wrong parameter {paramName} for voltage delay", parameters.LineInfo));
                        return(null);
                    }
                }
                else
                {
                    context.SetParameter(vd, "delay", parameter.Image);
                }
            }

            return(vd);
        }
        /// <summary>
        /// Generates a current switch.
        /// </summary>
        /// <param name="name">Name of current switch.</param>
        /// <param name="parameters">Parameters of current switch.</param>
        /// <param name="context">Reading context.</param>
        /// <returns>
        /// A new instance of current switch.
        /// </returns>
        private IEntity GenerateCurrentSwitch(string name, ParameterCollection parameters, ICircuitContext context)
        {
            if (parameters.Count < 4)
            {
                context.Result.Validation.Add(new ValidationEntry(ValidationEntrySource.Reader, ValidationEntryLevel.Warning, "Wrong parameter count for current switch", parameters.LineInfo));
                return(null);
            }

            string modelName = parameters.Get(3).Image;
            var    model     = context.ModelsRegistry.FindModel(modelName);

            if (model.Entity is ISwitchModel)
            {
                BehavioralResistor resistor = new BehavioralResistor(name);
                Model resistorModel         = model;
                context.CreateNodes(resistor, parameters.Take(2));
                var ic = $"i({parameters.Get(2)})";
                var iswitchModelParameters = resistorModel.Parameters as ISwitchModelParameters;

                double iOff = iswitchModelParameters.OffCurrent;
                double rOff = iswitchModelParameters.OffResistance;
                double iOn  = iswitchModelParameters.OnCurrent;
                double rOn  = iswitchModelParameters.OnResistance;

                double lm            = Math.Log(Math.Sqrt(rOn * rOff));
                double lr            = Math.Log(rOn / rOff);
                double im            = (iOn + iOff) / 2.0;
                double id            = iOn - iOff;
                var    resExpression = GetISwitchExpression(iOff, rOff, iOn, rOn, ic, lm, lr, im, id);
                resistor.Parameters.Expression  = resExpression;
                resistor.Parameters.ParseAction = (expression) =>
                {
                    var parser = new ExpressionParser(context.Evaluator.GetEvaluationContext(null), false, context.CaseSensitivity);
                    return(parser.Resolve(expression));
                };

                context.SimulationPreparations.ExecuteActionAfterSetup(
                    (simulation) =>
                {
                    if (context.ModelsRegistry is StochasticModelsRegistry stochasticModelsRegistry)
                    {
                        resistorModel = stochasticModelsRegistry.ProvideStochasticModel(name, simulation, model);

                        if (!context.Result.FindObject(resistorModel.Name, out _))
                        {
                            stochasticModelsRegistry.RegisterModelInstance(resistorModel);
                        }
                    }

                    iOff = iswitchModelParameters.OffCurrent;
                    rOff = iswitchModelParameters.OffResistance;
                    iOn  = iswitchModelParameters.OnCurrent;
                    rOn  = iswitchModelParameters.OnResistance;

                    lm            = Math.Log(Math.Sqrt(rOn * rOff));
                    lr            = Math.Log(rOn / rOff);
                    im            = (iOn + iOff) / 2.0;
                    id            = iOn - iOff;
                    resExpression = GetISwitchExpression(iOff, rOff, iOn, rOn, ic, lm, lr, im, id);
                    resistor.Parameters.Expression  = resExpression;
                    resistor.Parameters.ParseAction = (expression) =>
                    {
                        var parser = new ExpressionParser(context.Evaluator.GetEvaluationContext(simulation), false, context.CaseSensitivity);
                        return(parser.Resolve(expression));
                    };
                });
                return(resistor);
            }

            CurrentSwitch csw = new CurrentSwitch(name);

            context.CreateNodes(csw, parameters);

            // Get the controlling voltage source
            if (parameters[2] is WordParameter || parameters[2] is IdentifierParameter)
            {
                csw.ControllingSource = context.NameGenerator.GenerateObjectName(parameters.Get(2).Image);
            }
            else
            {
                context.Result.Validation.Add(new ValidationEntry(ValidationEntrySource.Reader, ValidationEntryLevel.Warning, "Voltage source name expected", parameters.LineInfo));
                return(null);
            }

            // Get the model
            context.SimulationPreparations.ExecuteActionBeforeSetup((simulation) =>
            {
                context.ModelsRegistry.SetModel(
                    csw,
                    simulation,
                    parameters.Get(3),
                    $"Could not find model {parameters.Get(3)} for current switch {name}",
                    (Context.Models.Model switchModel) => csw.Model = switchModel.Name,
                    context.Result);
            });

            // Optional on or off
            if (parameters.Count > 4)
            {
                switch (parameters.Get(4).Image.ToLower())
                {
                case "on":
                    csw.SetParameter("on", true);
                    break;

                case "off":
                    csw.SetParameter("off", true);
                    break;

                default:
                    context.Result.Validation.Add(new ValidationEntry(ValidationEntrySource.Reader, ValidationEntryLevel.Warning, "ON or OFF expected", parameters.LineInfo));
                    return(csw);
                }
            }

            return(csw);
        }
        /// <summary>
        /// Generate resistor.
        /// </summary>
        /// <param name="name">Name of resistor to generate.</param>
        /// <param name="parameters">Parameters and pins for resistor.</param>
        /// <param name="context">Reading context.</param>
        /// <returns>
        /// A new instance of resistor.
        /// </returns>
        protected IEntity GenerateRes(string name, ParameterCollection parameters, ICircuitContext context)
        {
            if (parameters.Count == 3)
            {
                var evalContext = context.Evaluator.GetEvaluationContext();

                // RName Node1 Node2 something
                var    something  = parameters[2];
                string expression = null;

                if (something is AssignmentParameter asp)
                {
                    expression = asp.Value;
                }
                else
                {
                    expression = something.Image;
                }

                if (evalContext.HaveSpiceProperties(expression) || evalContext.HaveFunctions(expression))
                {
                    BehavioralResistor behavioralResistor = new BehavioralResistor(name);
                    context.CreateNodes(behavioralResistor, parameters.Take(BehavioralResistor.BehavioralResistorPinCount));

                    behavioralResistor.Parameters.Expression  = expression;
                    behavioralResistor.Parameters.ParseAction = (expression) =>
                    {
                        var parser = new ExpressionParser(context.Evaluator.GetEvaluationContext(null), false, context.CaseSensitivity);
                        return(parser.Resolve(expression));
                    };

                    if (evalContext.HaveFunctions(expression))
                    {
                        context.SimulationPreparations.ExecuteActionBeforeSetup((simulation) =>
                        {
                            behavioralResistor.Parameters.Expression = expression.ToString();

                            behavioralResistor.Parameters.ParseAction = (expression) =>
                            {
                                var parser = new ExpressionParser(context.Evaluator.GetEvaluationContext(simulation), false, context.CaseSensitivity);
                                return(parser.Resolve(expression));
                            };
                        });
                    }

                    return(behavioralResistor);
                }
            }

            Resistor res = new Resistor(name);

            context.CreateNodes(res, parameters);

            if (parameters.Count == 3)
            {
                // RName Node1 Node2 something
                var something = parameters[2];

                // Check if something is a model name
                if ((something is WordParameter || something is IdentifierParameter) &&
                    context.ModelsRegistry.FindModel(parameters.Get(2).Image) != null)
                {
                    // RName Node1 Node2 modelName
                    context.Result.Validation.Add(
                        new ValidationEntry(
                            ValidationEntrySource.Reader,
                            ValidationEntryLevel.Warning,
                            $"R parameter needs to be specified",
                            parameters.LineInfo));
                    return(null);
                }

                // Check if something can be resistance
                if (!(something is WordParameter ||
                      something is IdentifierParameter ||
                      something is ValueParameter ||
                      something is ExpressionParameter ||
                      (something is AssignmentParameter ap && (ap.Name.ToLower() == "r" || ap.Name.ToLower() == "resistance"))))
                {
                    context.Result.Validation.Add(
                        new ValidationEntry(
                            ValidationEntrySource.Reader,
                            ValidationEntryLevel.Warning,
                            $"Third parameter needs to represent resistance of resistor",
                            parameters.LineInfo));

                    return(null);
                }

                // Set resistance
                if (something is AssignmentParameter asp)
                {
                    context.SetParameter(res, "resistance", asp, true, false);
                }
                else
                {
                    context.SetParameter(res, "resistance", something, true, false);
                }
            }
            else
            {
                var resistorParameters = new List <Parameter>(parameters.Skip(Resistor.ResistorPinCount).ToArray());

                // RName Node1 Node2 something param1 ...
                if (resistorParameters.Count == 0)
                {
                    context.Result.Validation.Add(
                        new ValidationEntry(
                            ValidationEntrySource.Reader,
                            ValidationEntryLevel.Warning,
                            $"Resistor doesn't have at least 3 parameters",
                            parameters.LineInfo));
                    return(null);
                }

                var something = resistorParameters[0];

                // Check if something is a model name
                bool hasModelSyntax = (something is WordParameter || something is IdentifierParameter) &&
                                      context.ModelsRegistry.FindModel(something.Image) != null;
                bool hasTcParameter = parameters.Any(
                    p => p is AssignmentParameter ap && ap.Name.Equals(
                        "tc",
                        false ? StringComparison.CurrentCulture : StringComparison.CurrentCultureIgnoreCase));

                AssignmentParameter tcParameter = null;

                if (hasTcParameter)
                {
                    tcParameter = (AssignmentParameter)parameters.Single(
                        p => p is AssignmentParameter ap && ap.Name.Equals(
                            "tc",
                            false ? StringComparison.CurrentCulture : StringComparison.CurrentCultureIgnoreCase));
                    resistorParameters.Remove(tcParameter);
                }

                if (hasModelSyntax)
                {
                    var modelNameParameter = resistorParameters[0];

                    // Ignore tc parameter on resistor ...
                    context.SimulationPreparations.ExecuteActionBeforeSetup((simulation) =>
                    {
                        context.ModelsRegistry.SetModel(
                            res,
                            simulation,
                            modelNameParameter,
                            $"Could not find model {modelNameParameter} for resistor {name}",
                            (Context.Models.Model model) => res.Model = model.Name,
                            context.Result);
                    });

                    resistorParameters.RemoveAt(0);

                    if (resistorParameters.Count > 0 && (resistorParameters[0] is WordParameter ||
                                                         resistorParameters[0] is IdentifierParameter ||
                                                         resistorParameters[0] is ValueParameter ||
                                                         resistorParameters[0] is ExpressionParameter))
                    {
                        context.SetParameter(res, "resistance", resistorParameters[0].Image, true, false);
                        resistorParameters.RemoveAt(0);
                    }
                }
                else
                {
                    if (hasTcParameter)
                    {
                        var model = new ResistorModel(res.Name + "_default_model");
                        if (tcParameter.Values.Count == 2)
                        {
                            context.SetParameter(model, "tc1", tcParameter.Values[0]);
                            context.SetParameter(model, "tc2", tcParameter.Values[1]);
                        }
                        else
                        {
                            context.SetParameter(model, "tc1", tcParameter.Value);
                        }

                        context.ModelsRegistry.RegisterModelInstance(new Context.Models.Model(model.Name, model, model.Parameters));
                        res.Model = model.Name;
                        context.Result.AddEntity(model);
                    }

                    // Check if something can be resistance
                    var resistanceParameter = resistorParameters[0];

                    if (!(resistanceParameter is WordParameter ||
                          resistanceParameter is IdentifierParameter ||
                          resistanceParameter is ValueParameter ||
                          resistanceParameter is ExpressionParameter ||
                          (resistanceParameter is AssignmentParameter ap && (ap.Name.ToLower() == "r" || ap.Name.ToLower() == "resistance"))))
                    {
                        context.Result.Validation.Add(
                            new ValidationEntry(
                                ValidationEntrySource.Reader,
                                ValidationEntryLevel.Warning,
                                $"Invalid value for resistance",
                                parameters.LineInfo));
                        return(null);
                    }

                    if (resistanceParameter is AssignmentParameter asp)
                    {
                        context.SetParameter(res, "resistance", asp.Value, true, false);
                    }
                    else
                    {
                        context.SetParameter(res, "resistance", resistanceParameter.Image, true, false);
                    }

                    resistorParameters.RemoveAt(0);
                }

                foreach (var parameter in resistorParameters)
                {
                    if (parameter is AssignmentParameter ap)
                    {
                        try
                        {
                            context.SetParameter(res, ap.Name, ap.Value);
                        }
                        catch (Exception e)
                        {
                            context.Result.Validation.Add(
                                new ValidationEntry(
                                    ValidationEntrySource.Reader,
                                    ValidationEntryLevel.Error,
                                    $"Can't set parameter for resistor: '{parameter.Image}'",
                                    parameters.LineInfo,
                                    exception: e));

                            return(null);
                        }
                    }
                    else
                    {
                        context.Result.Validation.Add(
                            new ValidationEntry(
                                ValidationEntrySource.Reader,
                                ValidationEntryLevel.Error,
                                $"Invalid parameter for resistor: '{parameter.Image}'",
                                parameters.LineInfo));

                        return(null);
                    }
                }
            }

            return(res);
        }
        /// <summary>
        ///  Generates a new capacitor.
        /// </summary>
        /// <param name="name">Name of capacitor to generate.</param>
        /// <param name="parameters">Parameters and pins for capacitor.</param>
        /// <param name="context">Reading context.</param>
        /// <returns>
        /// A new instance of capacitor.
        /// </returns>
        protected SpiceSharp.Components.IComponent GenerateCap(string name, ParameterCollection parameters, ICircuitContext context)
        {
            if (parameters.Count == 3)
            {
                // CXXXXXXX N1 N2 VALUE
                var evalContext = context.Evaluator.GetEvaluationContext();

                var    something  = parameters[2];
                string expression = null;

                if (something is AssignmentParameter asp)
                {
                    expression = $"({asp.Value}) * x";
                }
                else
                {
                    expression = $"({something.Image}) * x";
                }

                if (evalContext.HaveSpiceProperties(expression) || evalContext.HaveFunctions(expression))
                {
                    BehavioralCapacitor behavioralCapacitor = new BehavioralCapacitor(name);
                    context.CreateNodes(behavioralCapacitor, parameters.Take(BehavioralCapacitor.BehavioralCapacitorPinCount));

                    behavioralCapacitor.Parameters.Expression  = expression;
                    behavioralCapacitor.Parameters.ParseAction = (expression) =>
                    {
                        var parser = new ExpressionParser(context.Evaluator.GetEvaluationContext(null), false, context.CaseSensitivity);
                        return(parser.Resolve(expression));
                    };

                    evalContext.Parameters.Add("x", new SpiceSharpParser.Common.Evaluation.Expressions.ConstantExpression(1));

                    if (evalContext.HaveFunctions(expression))
                    {
                        context.SimulationPreparations.ExecuteActionBeforeSetup((simulation) =>
                        {
                            behavioralCapacitor.Parameters.Expression = expression.ToString();

                            behavioralCapacitor.Parameters.ParseAction = (expression) =>
                            {
                                var parser = new ExpressionParser(context.Evaluator.GetEvaluationContext(simulation), false, context.CaseSensitivity);
                                return(parser.Resolve(expression));
                            };
                        });
                    }

                    evalContext.Parameters.Remove("x");

                    return(behavioralCapacitor);
                }
            }

            var capacitor = new Capacitor(name);

            context.CreateNodes(capacitor, parameters);

            // Get TC Parameter
            Parameter tcParameter = parameters.FirstOrDefault(
                p => p is AssignmentParameter ap && ap.Name.Equals(
                    "tc",
                    false ? StringComparison.CurrentCulture : StringComparison.CurrentCultureIgnoreCase));

            if (tcParameter != null)
            {
                parameters.Remove(tcParameter);
            }

            bool modelBased = false;

            if (parameters.Count == 3)
            {
                // CXXXXXXX N1 N2 VALUE
                if (parameters[2] is ValueParameter)
                {
                    context.SetParameter(capacitor, "capacitance", parameters.Get(2), true, false);
                }
                else
                {
                    context.Result.Validation.Add(
                        new ValidationEntry(
                            ValidationEntrySource.Reader,
                            ValidationEntryLevel.Warning,
                            $"Wrong parameter value for capacitance",
                            parameters.LineInfo));
                    return(null);
                }
            }
            else
            {
                // CXXXXXXX N1 N2 <VALUE> <MNAME> <L=LENGTH> <W=WIDTH> <IC=VAL>

                // Examples:
                // CMOD 3 7 CMODEL L = 10u W = 1u
                // CMOD 3 7 CMODEL L = 10u W = 1u IC=1
                // CMOD 3 7 1.3 IC=1
                if (parameters[2] is ValueParameter)
                {
                    context.SetParameter(capacitor, "capacitance", parameters.Get(2), true, false);
                }
                else
                {
                    context.SimulationPreparations.ExecuteActionBeforeSetup((simulation) =>
                    {
                        context.ModelsRegistry.SetModel(
                            capacitor,
                            simulation,
                            parameters.Get(2),
                            $"Could not find model {parameters.Get(2)} for capacitor {name}",
                            (Context.Models.Model model) => capacitor.Model = model.Name,
                            context.Result);
                    });

                    modelBased = true;
                }

                SetParameters(context, capacitor, parameters.Skip(3), true);

                if (modelBased)
                {
                    var bp = capacitor.GetParameterSet <ModelParameters>();

                    /*if (bp == null || !bp.Length.Given)
                     * {
                     *  context.Result.Validation.Add(new ValidationEntry(ValidationEntrySource.Reader,
                     *      ValidationEntryLevel.Warning,
                     *      $"L needs to be specified", parameters.LineInfo));
                     *  return null;
                     * }*/
                }
            }

            if (tcParameter != null)
            {
                var tcParameterAssignment = tcParameter as AssignmentParameter;

                if (tcParameterAssignment == null)
                {
                    context.Result.Validation.Add(
                        new ValidationEntry(
                            ValidationEntrySource.Reader,
                            ValidationEntryLevel.Warning,
                            $"TC needs to be assignment parameter",
                            parameters.LineInfo));
                    return(null);
                }

                if (modelBased)
                {
                    var model = context.ModelsRegistry.FindModelEntity(parameters.Get(2).Image);

                    if (tcParameterAssignment.Values.Count == 2)
                    {
                        context.SetParameter(model, "tc1", tcParameterAssignment.Values[0], true, false);
                        context.SetParameter(model, "tc2", tcParameterAssignment.Values[1], true, false);
                    }
                    else
                    {
                        context.SetParameter(model, "tc1", tcParameterAssignment.Value);
                    }

                    context.Result.AddEntity(model);
                    capacitor.Model = model.Name;
                }
                else
                {
                    var model = new CapacitorModel(capacitor.Name + "_default_model");
                    if (tcParameterAssignment.Values.Count == 2)
                    {
                        context.SetParameter(model, "tc1", tcParameterAssignment.Values[0], true, false);
                        context.SetParameter(model, "tc2", tcParameterAssignment.Values[1], true, false);
                    }
                    else
                    {
                        context.SetParameter(model, "tc1", tcParameterAssignment.Value);
                    }

                    context.ModelsRegistry.RegisterModelInstance(new Context.Models.Model(model.Name, model, model.Parameters));
                    context.Result.AddEntity(model);
                    capacitor.Model = model.Name;
                }
            }

            return(capacitor);
        }
        /// <summary>
        ///  Generates a new capacitor.
        /// </summary>
        /// <param name="name">Name of capacitor to generate.</param>
        /// <param name="parameters">Parameters and pins for capacitor.</param>
        /// <param name="context">Reading context.</param>
        /// <returns>
        /// A new instance of capacitor.
        /// </returns>
        protected SpiceSharp.Components.Component GenerateCap(string name, ParameterCollection parameters, ICircuitContext context)
        {
            var capacitor = new Capacitor(name);

            context.CreateNodes(capacitor, parameters);

            // Get TC Parameter
            Parameter tcParameter = parameters.FirstOrDefault(
                p => p is AssignmentParameter ap && ap.Name.Equals(
                    "tc",
                    context.CaseSensitivity.IsEntityParameterNameCaseSensitive ? StringComparison.CurrentCulture : StringComparison.CurrentCultureIgnoreCase));

            if (tcParameter != null)
            {
                parameters.Remove(tcParameter);
            }

            bool modelBased = false;

            if (parameters.Count == 3)
            {
                // CXXXXXXX N1 N2 VALUE
                if (parameters[2] is ExpressionParameter || parameters[2] is ValueParameter)
                {
                    context.SetParameter(capacitor, "capacitance", parameters.Get(2));
                }
                else
                {
                    context.Result.Validation.Add(new ValidationEntry(ValidationEntrySource.Reader,
                                                                      ValidationEntryLevel.Warning,
                                                                      $"Wrong parameter value for capacitance", parameters.LineInfo));
                    return(null);
                }
            }
            else
            {
                // CXXXXXXX N1 N2 <VALUE> <MNAME> <L=LENGTH> <W=WIDTH> <IC=VAL>

                // Examples:
                // CMOD 3 7 CMODEL L = 10u W = 1u
                // CMOD 3 7 CMODEL L = 10u W = 1u IC=1
                // CMOD 3 7 1.3 IC=1
                if (parameters[2] is ExpressionParameter || parameters[2] is ValueParameter)
                {
                    context.SetParameter(capacitor, "capacitance", parameters.Get(2));
                }
                else
                {
                    context.SimulationPreparations.ExecuteActionBeforeSetup((simulation) =>
                    {
                        context.ModelsRegistry.SetModel(
                            capacitor,
                            simulation,
                            parameters.Get(2),
                            $"Could not find model {parameters.Get(2)} for capacitor {name}",
                            (CapacitorModel model) => capacitor.Model = model.Name,
                            context.Result);
                    });

                    modelBased = true;
                }

                SetParameters(context, capacitor, parameters.Skip(3), true);

                if (modelBased)
                {
                    var bp = capacitor.ParameterSets[typeof(SpiceSharp.Components.CapacitorBehaviors.BaseParameters)] as SpiceSharp.Components.CapacitorBehaviors.BaseParameters;
                    if (bp == null || !bp.Length.Given)
                    {
                        context.Result.Validation.Add(new ValidationEntry(ValidationEntrySource.Reader,
                                                                          ValidationEntryLevel.Warning,
                                                                          $"L needs to be specified", parameters.LineInfo));
                        return(null);
                    }
                }
            }

            if (tcParameter != null)
            {
                var tcParameterAssignment = tcParameter as AssignmentParameter;

                if (tcParameterAssignment == null)
                {
                    context.Result.Validation.Add(new ValidationEntry(ValidationEntrySource.Reader,
                                                                      ValidationEntryLevel.Warning,
                                                                      $"TC needs to be assignment parameter", parameters.LineInfo));
                    return(null);
                }

                if (modelBased)
                {
                    var model = context.ModelsRegistry.FindModel <CapacitorModel>(parameters.Get(2).Image);

                    if (tcParameterAssignment.Values.Count == 2)
                    {
                        context.SetParameter(model, "tc1", tcParameterAssignment.Values[0]);
                        context.SetParameter(model, "tc2", tcParameterAssignment.Values[1]);
                    }
                    else
                    {
                        context.SetParameter(model, "tc1", tcParameterAssignment.Value);
                    }

                    context.Result.AddEntity(model);
                    capacitor.Model = model.Name;
                }
                else
                {
                    var model = new CapacitorModel(capacitor.Name + "_default_model");
                    if (tcParameterAssignment.Values.Count == 2)
                    {
                        context.SetParameter(model, "tc1", tcParameterAssignment.Values[0]);
                        context.SetParameter(model, "tc2", tcParameterAssignment.Values[1]);
                    }
                    else
                    {
                        context.SetParameter(model, "tc1", tcParameterAssignment.Value);
                    }

                    context.ModelsRegistry.RegisterModelInstance(model);
                    context.Result.AddEntity(model);
                    capacitor.Model = model.Name;
                }
            }

            return(capacitor);
        }
Exemplo n.º 13
0
        public IEntity Generate(string componentIdentifier, string originalName, string type, ParameterCollection parameters, ICircuitContext context)
        {
            if (parameters.Count < 4)
            {
                throw new System.Exception("Model expected");
            }

            JFET jfet = new JFET(componentIdentifier);

            context.CreateNodes(jfet, parameters);

            context.SimulationPreparations.ExecuteActionBeforeSetup((simulation) =>
            {
                context.ModelsRegistry.SetModel(
                    jfet,
                    simulation,
                    parameters.Get(3),
                    $"Could not find model {parameters.Get(3)} for JFET {originalName}",
                    (Context.Models.Model model) => jfet.Model = model.Name,
                    context.Result);
            });

            // Read the rest of the parameters
            for (int i = 3; i < parameters.Count; i++)
            {
                if (parameters[i] is WordParameter w)
                {
                    if (w.Image.ToLower() == "off")
                    {
                        jfet.SetParameter("off", true);
                    }
                }

                if (parameters[i] is AssignmentParameter asg)
                {
                    if (asg.Name.ToLower() == "ic")
                    {
                        if (asg.Value.Length == 2)
                        {
                            context.SetParameter(jfet, "ic-vds", asg.Values[0]);
                            context.SetParameter(jfet, "ic-vgs", asg.Values[1]);
                        }

                        if (asg.Value.Length == 1)
                        {
                            context.SetParameter(jfet, "ic-vds", asg.Values[0]);
                        }
                    }
                    else if (asg.Name.ToLower() == "temp")
                    {
                        context.SetParameter(jfet, "temp", asg.Value);
                    }
                    else if (asg.Name.ToLower() == "area")
                    {
                        context.SetParameter(jfet, "area", asg.Value);
                    }
                    else
                    {
                        throw new System.Exception("Unknown parameter: " + asg.Name);
                    }
                }

                if (parameters[i] is ValueParameter || parameters[i] is ExpressionParameter)
                {
                    context.SetParameter(jfet, "area", parameters[i].Image);
                }
            }

            return(jfet);
        }
        /// <summary>
        /// Generate resistor.
        /// </summary>
        /// <param name="name">Name of resistor to generate.</param>
        /// <param name="parameters">Parameters and pins for resistor.</param>
        /// <param name="context">Reading context.</param>
        /// <returns>
        /// A new instance of resistor.
        /// </returns>
        protected SpiceSharp.Components.Component GenerateRes(string name, ParameterCollection parameters, ICircuitContext context)
        {
            Resistor res = new Resistor(name);

            var dynamicParameter = parameters.FirstOrDefault(p => p.Image == "dynamic");

            if (dynamicParameter != null)
            {
                parameters.Remove(dynamicParameter);
            }

            bool isDynamic = dynamicParameter != null || context.Result?.SimulationConfiguration?.DynamicResistors == true;

            if (isDynamic)
            {
                context.SimulationPreparations.ExecuteTemperatureBehaviorBeforeLoad(res);
            }

            context.CreateNodes(res, parameters);

            if (parameters.Count == 3)
            {
                // RName Node1 Node2 something
                var something = parameters[2];

                // Check if something is a model name
                if ((something is WordParameter || something is IdentifierParameter) &&
                    context.ModelsRegistry.FindModel <ResistorModel>(parameters.Get(2).Image) != null)
                {
                    // RName Node1 Node2 modelName
                    context.Result.Validation.Add(new ValidationEntry(ValidationEntrySource.Reader,
                                                                      ValidationEntryLevel.Warning,
                                                                      $"R parameter needs to be specified", parameters.LineInfo));
                    return(null);
                }

                // Check if something can be resistance
                if (!(something is WordParameter ||
                      something is IdentifierParameter ||
                      something is ValueParameter ||
                      something is ExpressionParameter ||
                      (something is AssignmentParameter ap && (ap.Name.ToLower() == "r" || ap.Name.ToLower() == "resistance"))))
                {
                    context.Result.Validation.Add(new ValidationEntry(ValidationEntrySource.Reader,
                                                                      ValidationEntryLevel.Warning,
                                                                      $"Third parameter needs to represent resistance of resistor", parameters.LineInfo));
                    return(null);
                }

                // Set resistance
                if (something is AssignmentParameter asp)
                {
                    context.SetParameter(res, "resistance", asp, true, isDynamic);
                }
                else
                {
                    context.SetParameter(res, "resistance", something, true, isDynamic);
                }
            }
            else
            {
                var resistorParameters = new List <Parameter>(parameters.Skip(Resistor.ResistorPinCount).ToArray());

                // RName Node1 Node2 something param1 ...
                if (resistorParameters.Count == 0)
                {
                    context.Result.Validation.Add(new ValidationEntry(ValidationEntrySource.Reader,
                                                                      ValidationEntryLevel.Warning,
                                                                      $"Resistor doesn't have at least 3 parameters", parameters.LineInfo));
                    return(null);
                }

                var something = resistorParameters[0];

                // Check if something is a model name
                bool hasModelSyntax = (something is WordParameter || something is IdentifierParameter) &&
                                      context.ModelsRegistry.FindModel <ResistorModel>(something.Image) != null;
                bool hasTcParameter = parameters.Any(
                    p => p is AssignmentParameter ap && ap.Name.Equals(
                        "tc",
                        context.CaseSensitivity.IsEntityParameterNameCaseSensitive ? StringComparison.CurrentCulture : StringComparison.CurrentCultureIgnoreCase));

                AssignmentParameter tcParameter = null;

                if (hasTcParameter)
                {
                    tcParameter = (AssignmentParameter)parameters.Single(
                        p => p is AssignmentParameter ap && ap.Name.Equals(
                            "tc",
                            context.CaseSensitivity.IsEntityParameterNameCaseSensitive ? StringComparison.CurrentCulture : StringComparison.CurrentCultureIgnoreCase));
                    resistorParameters.Remove(tcParameter);
                }

                if (hasModelSyntax)
                {
                    var modelNameParameter = resistorParameters[0];

                    // Ignore tc parameter on resistor ...
                    context.SimulationPreparations.ExecuteActionBeforeSetup((simulation) =>
                    {
                        context.ModelsRegistry.SetModel(
                            res,
                            simulation,
                            modelNameParameter,
                            $"Could not find model {modelNameParameter} for resistor {name}",
                            (ResistorModel model) => res.Model = model.Name,
                            context.Result);
                    });

                    resistorParameters.RemoveAt(0);

                    if (resistorParameters.Count > 0 && (resistorParameters[0] is WordParameter ||
                                                         resistorParameters[0] is IdentifierParameter ||
                                                         resistorParameters[0] is ValueParameter ||
                                                         resistorParameters[0] is ExpressionParameter))
                    {
                        context.SetParameter(res, "resistance", resistorParameters[0].Image, true);
                        resistorParameters.RemoveAt(0);
                    }
                }
                else
                {
                    if (hasTcParameter)
                    {
                        var model = new ResistorModel(res.Name + "_default_model");
                        if (tcParameter.Values.Count == 2)
                        {
                            context.SetParameter(model, "tc1", tcParameter.Values[0]);
                            context.SetParameter(model, "tc2", tcParameter.Values[1]);
                        }
                        else
                        {
                            context.SetParameter(model, "tc1", tcParameter.Value);
                        }

                        context.ModelsRegistry.RegisterModelInstance(model);
                        res.Model = model.Name;
                        context.Result.AddEntity(model);
                    }

                    // Check if something can be resistance
                    var resistanceParameter = resistorParameters[0];

                    if (!(resistanceParameter is WordParameter ||
                          resistanceParameter is IdentifierParameter ||
                          resistanceParameter is ValueParameter ||
                          resistanceParameter is ExpressionParameter ||
                          (resistanceParameter is AssignmentParameter ap && !(ap.Name.ToLower() == "r" || ap.Name.ToLower() == "resistance"))))
                    {
                        context.Result.Validation.Add(new ValidationEntry(ValidationEntrySource.Reader,
                                                                          ValidationEntryLevel.Warning,
                                                                          $"Invalid value for resistance", parameters.LineInfo));
                        return(null);
                    }

                    if (resistanceParameter is AssignmentParameter asp)
                    {
                        context.SetParameter(res, "resistance", asp.Value, true, isDynamic);
                    }
                    else
                    {
                        context.SetParameter(res, "resistance", resistanceParameter.Image, true, isDynamic);
                    }

                    resistorParameters.RemoveAt(0);
                }

                foreach (var parameter in resistorParameters)
                {
                    if (parameter is AssignmentParameter ap)
                    {
                        try
                        {
                            context.SetParameter(res, ap.Name, ap.Value);
                        }
                        catch (Exception e)
                        {
                            context.Result.Validation.Add(new ValidationEntry(ValidationEntrySource.Reader,
                                                                              ValidationEntryLevel.Warning,
                                                                              $"Can't set parameter for resistor: '{parameter.Image}'", parameters.LineInfo));
                            return(null);
                        }
                    }
                    else
                    {
                        context.Result.Validation.Add(new ValidationEntry(ValidationEntrySource.Reader,
                                                                          ValidationEntryLevel.Warning,
                                                                          $"Invalid parameter for resistor: '{parameter.Image}'", parameters.LineInfo));
                        return(null);
                    }
                }
            }

            return(res);
        }
        /// <summary>
        /// Generates a voltage switch.
        /// </summary>
        /// <param name="name">Name of voltage switch to generate.</param>
        /// <param name="parameters">Parameters for voltage switch.</param>
        /// <param name="context">Reading context.</param>
        /// <returns>
        /// A new voltage switch.
        /// </returns>
        protected IEntity GenerateVoltageSwitch(string name, ParameterCollection parameters, ICircuitContext context)
        {
            if (parameters.Count < 5)
            {
                context.Result.Validation.Add(new ValidationEntry(ValidationEntrySource.Reader, ValidationEntryLevel.Warning, "Wrong parameter count for voltage switch", parameters.LineInfo));
                return(null);
            }

            string modelName = parameters.Get(4).Image;

            var model = context.ModelsRegistry.FindModel(modelName);

            if (model.Entity is VSwitchModel)
            {
                BehavioralResistor resistor = new BehavioralResistor(name);
                Model resistorModel         = model;
                context.CreateNodes(resistor, parameters.Take(BehavioralResistor.BehavioralResistorPinCount));
                var vSwitchModelParameters = resistorModel.Parameters as VSwitchModelParameters;

                double vOff = vSwitchModelParameters.OffVoltage;
                double rOff = vSwitchModelParameters.OffResistance;
                double vOn  = vSwitchModelParameters.OnVoltage;
                double rOn  = vSwitchModelParameters.OnResistance;

                string vc            = $"v({parameters.Get(2)}, {parameters.Get(3)})";
                double lm            = Math.Log(Math.Sqrt(rOn * rOff));
                double lr            = Math.Log(rOn / rOff);
                double vm            = (vOn + vOff) / 2.0;
                double vd            = vOn - vOff;
                string resExpression = GetVSwitchExpression(vOff, rOff, vOn, rOn, vc, lm, lr, vm, vd);

                resistor.Parameters.Expression  = resExpression;
                resistor.Parameters.ParseAction = (expression) =>
                {
                    var parser = new ExpressionParser(context.Evaluator.GetEvaluationContext(null), false, context.CaseSensitivity);
                    return(parser.Resolve(expression));
                };

                context.SimulationPreparations.ExecuteActionAfterSetup(
                    (simulation) =>
                {
                    if (context.ModelsRegistry is StochasticModelsRegistry stochasticModelsRegistry)
                    {
                        resistorModel = stochasticModelsRegistry.ProvideStochasticModel(name, simulation, model);

                        if (!context.Result.FindObject(resistorModel.Name, out _))
                        {
                            stochasticModelsRegistry.RegisterModelInstance(resistorModel);
                        }
                    }

                    vOff          = vSwitchModelParameters.OffVoltage;
                    rOff          = vSwitchModelParameters.OffResistance;
                    vOn           = vSwitchModelParameters.OnVoltage;
                    rOn           = vSwitchModelParameters.OnResistance;
                    lm            = Math.Log(Math.Sqrt(rOn * rOff));
                    lr            = Math.Log(rOn / rOff);
                    vm            = (vOn + vOff) / 2.0;
                    vd            = vOn - vOff;
                    resExpression = GetVSwitchExpression(vOff, rOff, vOn, rOn, vc, lm, lr, vm, vd);
                    resistor.Parameters.Expression  = resExpression;
                    resistor.Parameters.ParseAction = (expression) =>
                    {
                        var parser = new ExpressionParser(context.Evaluator.GetEvaluationContext(simulation), false, context.CaseSensitivity);
                        return(parser.Resolve(expression));
                    };
                });
                return(resistor);
            }

            VoltageSwitch vsw = new VoltageSwitch(name);

            context.CreateNodes(vsw, parameters);

            context.SimulationPreparations.ExecuteActionBeforeSetup((simulation) =>
            {
                context.ModelsRegistry.SetModel(
                    vsw,
                    simulation,
                    parameters.Get(4),
                    $"Could not find model {parameters.Get(4)} for voltage switch {name}",
                    (Context.Models.Model model2) => { vsw.Model = model2.Name; },
                    context.Result);
            });

            // Optional ON or OFF
            if (parameters.Count == 6)
            {
                switch (parameters.Get(5).Image.ToLower())
                {
                case "on":
                    vsw.SetParameter("on", true);
                    break;

                case "off":
                    vsw.SetParameter("off", true);
                    break;

                default:
                    context.Result.Validation.Add(new ValidationEntry(ValidationEntrySource.Reader, ValidationEntryLevel.Warning, "ON or OFF expected", parameters.LineInfo));
                    return(vsw);
                }
            }
            else if (parameters.Count > 6)
            {
                context.Result.Validation.Add(new ValidationEntry(ValidationEntrySource.Reader, ValidationEntryLevel.Warning, "Too many parameters for voltage switch", parameters.LineInfo));
                return(vsw);
            }

            return(vsw);
        }
        public override IEntity Generate(string componentIdentifier, string originalName, string type, SpiceSharpParser.Models.Netlist.Spice.Objects.ParameterCollection parameters, ICircuitContext context)
        {
            // Errors
            switch (parameters.Count)
            {
            case 0:
                context.Result.Validation.Add(
                    new ValidationEntry(
                        ValidationEntrySource.Reader,
                        ValidationEntryLevel.Error,
                        $"Node expected for component {componentIdentifier}",
                        parameters.LineInfo));
                return(null);

            case 1:
            case 2:
            case 3:
                context.Result.Validation.Add(
                    new ValidationEntry(
                        ValidationEntrySource.Reader,
                        ValidationEntryLevel.Error,
                        $"Node expected",
                        parameters.LineInfo));
                return(null);

            case 4:
                context.Result.Validation.Add(
                    new ValidationEntry(
                        ValidationEntrySource.Reader,
                        ValidationEntryLevel.Error,
                        $"Model name expected",
                        parameters.LineInfo));
                return(null);
            }

            // Get the model and generate a component for it
            SpiceSharp.Components.Component mosfet = null;
            var modelNameParameter = parameters.Get(4);
            var model = context.ModelsRegistry.FindModel(modelNameParameter.Image);

            if (model == null)
            {
                context.Result.Validation.Add(
                    new ValidationEntry(
                        ValidationEntrySource.Reader,
                        ValidationEntryLevel.Error,
                        $"Could not find model {modelNameParameter.Image} for mosfet {originalName}",
                        parameters.LineInfo));

                return(null);
            }

            if (Mosfets.ContainsKey(model.GetType()))
            {
                var mosfetDetails = Mosfets[model.GetType()].Invoke(componentIdentifier);
                mosfet = mosfetDetails.Mosfet;

                context.SimulationPreparations.ExecuteActionBeforeSetup((simulation) =>
                {
                    context.ModelsRegistry.SetModel(
                        mosfetDetails.Mosfet,
                        simulation,
                        modelNameParameter,
                        $"Could not find model {modelNameParameter.Image} for mosfet {componentIdentifier}",
                        mosfetDetails.SetModelAction,
                        context.Result);
                });
            }
            else
            {
                context.Result.Validation.Add(
                    new ValidationEntry(
                        ValidationEntrySource.Reader,
                        ValidationEntryLevel.Error,
                        $"Invalid model {model.GetType()} for {componentIdentifier}",
                        parameters.LineInfo));

                return(null);
            }

            // The rest is all just parameters
            context.CreateNodes(mosfet, parameters);
            SetParameters(context, mosfet, parameters.Skip(5), true);
            return(mosfet);
        }
Exemplo n.º 17
0
        public SpiceSharp.Components.Component Generate(string componentIdentifier, string originalName, string type, ParameterCollection parameters, ICircuitContext context)
        {
            BipolarJunctionTransistor bjt = new BipolarJunctionTransistor(componentIdentifier);

            // If the component is of the format QXXX NC NB NE MNAME off we will insert NE again before the model name
            if (parameters.Count == 5 && parameters[4] is WordParameter w && w.Image == "off")
            {
                parameters.Insert(3, parameters[2]);
            }

            // If the component is of the format QXXX NC NB NE MNAME we will insert NE again before the model name
            if (parameters.Count == 4)
            {
                parameters.Insert(3, parameters[2]);
            }

            context.CreateNodes(bjt, parameters);

            if (parameters.Count < 5)
            {
                context.Result.Validation.Add(new ValidationEntry(ValidationEntrySource.Reader, ValidationEntryLevel.Warning, "Wrong parameters count for BJT", parameters.LineInfo));
                return(null);
            }

            context.SimulationPreparations.ExecuteActionBeforeSetup((simulation) =>
            {
                context.ModelsRegistry.SetModel(
                    bjt,
                    simulation,
                    parameters.Get(4),
                    $"Could not find model {parameters.Get(4)} for BJT {originalName}",
                    (BipolarJunctionTransistorModel model) => bjt.Model = model.Name,
                    context.Result);
            });

            for (int i = 5; i < parameters.Count; i++)
            {
                var parameter = parameters[i];

                if (parameter is SingleParameter s)
                {
                    if (s is WordParameter)
                    {
                        switch (s.Image.ToLower())
                        {
                        case "on": bjt.SetParameter("off", false); break;

                        case "off": bjt.SetParameter("on", false); break;

                        default: throw new System.Exception();
                        }
                    }
                    else
                    {
                        // TODO: Fix this please it's broken ...
                        BaseParameters bp = bjt.ParameterSets.Get <BaseParameters>();
                        if (!bp.Area.Given)
                        {
                            bp.Area.Value = context.Evaluator.EvaluateDouble(s.Image);
                        }

                        if (!bp.Temperature.Given)
                        {
                            bp.Temperature.Value = context.Evaluator.EvaluateDouble(s.Image);
                        }
                    }
                }

                if (parameter is AssignmentParameter asg)
                {
                    if (asg.Name.ToLower() == "ic")
                    {
                        context.SetParameter(bjt, "ic", asg.Value);
                    }
                }
            }

            return(bjt);
        }
Exemplo n.º 18
0
        public SpiceSharp.Components.Component Generate(string componentIdentifier, string originalName, string type, ParameterCollection parameters, ICircuitContext context)
        {
            if (parameters.Count < 3)
            {
                throw new System.Exception("Model expected");
            }

            Diode diode = new Diode(componentIdentifier);

            context.CreateNodes(diode, parameters);

            context.SimulationPreparations.ExecuteActionBeforeSetup((simulation) =>
            {
                context.ModelsRegistry.SetModel(
                    diode,
                    simulation,
                    parameters.Get(2),
                    $"Could not find model {parameters.Get(2)} for diode {originalName}",
                    (DiodeModel model) => diode.Model = model.Name,
                    context.Result);
            });

            // Read the rest of the parameters
            for (int i = 3; i < parameters.Count; i++)
            {
                if (parameters[i] is WordParameter w)
                {
                    if (w.Image.ToLower() == "on")
                    {
                        diode.SetParameter("off", false);
                    }
                    else if (w.Image.ToLower() == "off")
                    {
                        diode.SetParameter("off", true);
                    }
                    else
                    {
                        throw new System.Exception("Expected on/off for diode");
                    }
                }

                if (parameters[i] is AssignmentParameter asg)
                {
                    if (asg.Name.ToLower() == "ic")
                    {
                        context.SetParameter(diode, "ic", asg.Value);
                    }
                }

                if (parameters[i] is ValueParameter || parameters[i] is ExpressionParameter)
                {
                    // TODO: Fix this please it's broken ...
                    var bp = diode.ParameterSets.Get <SpiceSharp.Components.DiodeBehaviors.BaseParameters>();
                    if (!bp.Area.Given)
                    {
                        bp.Area.Value = context.Evaluator.EvaluateDouble(parameters.Get(i));
                    }
                    else
                    {
                        if (!bp.Temperature.Given)
                        {
                            bp.Temperature.Value = context.Evaluator.EvaluateDouble(parameters.Get(i));
                        }
                    }
                }
            }

            return(diode);
        }
        /// <summary>
        /// Generates a current switch.
        /// </summary>
        /// <param name="name">Name of current switch.</param>
        /// <param name="parameters">Parameters of current switch.</param>
        /// <param name="context">Reading context.</param>
        /// <returns>
        /// A new instance of current switch.
        /// </returns>
        protected SpiceSharp.Components.Component GenerateCurrentSwitch(string name, ParameterCollection parameters, ICircuitContext context)
        {
            if (parameters.Count < 4)
            {
                context.Result.Validation.Add(new ValidationEntry(ValidationEntrySource.Reader, ValidationEntryLevel.Warning, "Wrong parameter count for current switch", parameters.LineInfo));
                return(null);
            }

            string modelName = parameters.Get(3).Image;

            if (context.ModelsRegistry.FindModel <Model>(modelName) is ISwitchModel s)
            {
                Resistor resistor      = new Resistor(name);
                Model    resistorModel = s;
                context.CreateNodes(resistor, parameters.Take(2));
                context.SimulationPreparations.ExecuteTemperatureBehaviorBeforeLoad(resistor);

                context.SimulationPreparations.ExecuteActionBeforeSetup(
                    (simulation) =>
                {
                    if (context.ModelsRegistry is StochasticModelsRegistry stochasticModelsRegistry)
                    {
                        resistorModel = stochasticModelsRegistry.ProvideStochasticModel(name, simulation, s);

                        if (!context.Result.FindObject(resistorModel.Name, out _))
                        {
                            stochasticModelsRegistry.RegisterModelInstance(resistorModel);
                            context.Result.Circuit.Add(resistorModel);
                        }
                    }

                    double rOff = resistorModel.ParameterSets.GetParameter <double>("roff");

                    string resExpression = $"pos(table(i({parameters.Get(2)}), @{resistorModel.Name}[ioff], @{resistorModel.Name}[roff] , @{resistorModel.Name}[ion], @{resistorModel.Name}[ron]), {rOff.ToString(CultureInfo.InvariantCulture)})";
                    context.SetParameter(resistor, "resistance", resExpression, beforeTemperature: true, onload: true);
                });
                return(resistor);
            }
            else
            {
                CurrentSwitch csw = new CurrentSwitch(name);
                context.CreateNodes(csw, parameters);

                // Get the controlling voltage source
                if (parameters[2] is WordParameter || parameters[2] is IdentifierParameter)
                {
                    csw.ControllingName = context.NameGenerator.GenerateObjectName(parameters.Get(2).Image);
                }
                else
                {
                    context.Result.Validation.Add(new ValidationEntry(ValidationEntrySource.Reader, ValidationEntryLevel.Warning, "Voltage source name expected", parameters.LineInfo));
                    return(null);
                }

                // Get the model
                context.SimulationPreparations.ExecuteActionBeforeSetup((simulation) =>
                {
                    context.ModelsRegistry.SetModel(
                        csw,
                        simulation,
                        parameters.Get(3),
                        $"Could not find model {parameters.Get(3)} for current switch {name}",
                        (CurrentSwitchModel model) => csw.Model = model.Name,
                        context.Result);
                });

                // Optional on or off
                if (parameters.Count > 4)
                {
                    switch (parameters.Get(4).Image.ToLower())
                    {
                    case "on":
                        csw.ParameterSets.SetParameter("on");
                        break;

                    case "off":
                        csw.ParameterSets.SetParameter("off");
                        break;

                    default:
                        context.Result.Validation.Add(new ValidationEntry(ValidationEntrySource.Reader, ValidationEntryLevel.Warning, "ON or OFF expected", parameters.LineInfo));
                        return(csw);
                    }
                }

                return(csw);
            }
        }
        protected void SetSourceParameters(
            string name,
            ParameterCollection parameters,
            ICircuitContext context,
            Component component)
        {
            var originalParameters = parameters;

            parameters = parameters.Skip(VoltageSource.VoltageSourcePinCount);

            var acParameter = parameters.FirstOrDefault(p => p.Image.ToLower() == "ac");

            if (acParameter != null)
            {
                int acParameterIndex = parameters.IndexOf(acParameter);

                if (acParameterIndex != parameters.Count - 1)
                {
                    var acParameterValue = parameters.Get(acParameterIndex + 1);
                    context.SetParameter(component, "acmag", acParameterValue);

                    if (acParameterIndex + 1 != parameters.Count - 1)
                    {
                        // Check first if next parameter is waveform
                        var acPhaseCandidate = parameters[acParameterIndex + 2].Image;
                        if (parameters[acParameterIndex + 2] is SingleParameter &&
                            !context.WaveformReader.Supports(acPhaseCandidate, context) &&
                            acPhaseCandidate.ToLower() != "dc")
                        {
                            var acPhaseParameterValue = parameters.Get(acParameterIndex + 2);
                            context.SetParameter(component, "acphase", acPhaseParameterValue);

                            parameters.RemoveAt(acParameterIndex + 2);
                        }
                    }

                    parameters.RemoveAt(acParameterIndex + 1);
                }

                parameters.RemoveAt(acParameterIndex);
            }

            // 2. Set DC
            var dcParameter = parameters.FirstOrDefault(p => p.Image.ToLower() == "dc");

            if (dcParameter != null)
            {
                int dcParameterIndex = parameters.IndexOf(dcParameter);
                if (dcParameterIndex != parameters.Count - 1)
                {
                    var dcParameterValue = parameters.Get(dcParameterIndex + 1);
                    context.SetParameter(component, "dc", dcParameterValue);
                    parameters.RemoveAt(dcParameterIndex + 1);
                }

                parameters.RemoveAt(dcParameterIndex);
            }
            else
            {
                if (parameters.Count > 0 &&
                    parameters[0] is SingleParameter sp &&
                    !context.WaveformReader.Supports(sp.Image, context) &&
                    parameters[0].Image.ToLower() != "value")
                {
                    context.SetParameter(component, "dc", sp);
                    parameters.RemoveAt(0);
                }
            }

            // 3. Set up waveform
            if (parameters.Count > 0)
            {
                var firstParameter = parameters[0];

                if (firstParameter is BracketParameter bp)
                {
                    if (context.WaveformReader.Supports(bp.Name, context))
                    {
                        component.SetParameter("waveform", context.WaveformReader.Generate(bp.Name, bp.Parameters, context));
                    }
                    else
                    {
                        context.Result.Validation.Add(new ValidationEntry(ValidationEntrySource.Reader, ValidationEntryLevel.Warning, $"Unsupported waveform: {bp.Name}", bp.LineInfo));
                    }
                }
                else
                {
                    if (firstParameter is WordParameter wp && wp.Image.ToLower() != "value")
                    {
                        if (context.WaveformReader.Supports(wp.Image, context))
                        {
                            component.SetParameter("waveform", context.WaveformReader.Generate(wp.Image, parameters.Skip(1), context));
                        }
                        else
                        {
                            context.Result.Validation.Add(new ValidationEntry(ValidationEntrySource.Reader, ValidationEntryLevel.Warning, $"Unsupported waveform: {wp}", wp.LineInfo));
                        }
                    }
                }

                if (firstParameter is AssignmentParameter ap && ap.Name.ToLower() == "value")
                {
                    context.SetParameter(component, "dc", ap.Value);
                }

                if (parameters.Count >= 2 &&
                    parameters[0].Image.ToLower() == "value" &&
                    parameters[1] is SingleParameter)
                {
                    context.SetParameter(component, "dc", parameters[1].Image);
                }
            }

            context.CreateNodes(component, originalParameters);
        }
        /// <summary>
        /// Generates a voltage switch.
        /// </summary>
        /// <param name="name">Name of voltage switch to generate.</param>
        /// <param name="parameters">Parameters for voltage switch.</param>
        /// <param name="context">Reading context.</param>
        /// <returns>
        /// A new voltage switch.
        /// </returns>
        protected SpiceSharp.Components.Component GenerateVoltageSwitch(string name, ParameterCollection parameters, ICircuitContext context)
        {
            if (parameters.Count < 5)
            {
                context.Result.Validation.Add(new ValidationEntry(ValidationEntrySource.Reader, ValidationEntryLevel.Warning, "Wrong parameter count for voltage switch", parameters.LineInfo));
                return(null);
            }

            string modelName = parameters.Get(4).Image;

            if (context.ModelsRegistry.FindModel <Model>(modelName) is VSwitchModel vmodel)
            {
                Resistor resistor      = new Resistor(name);
                Model    resistorModel = vmodel;
                context.CreateNodes(resistor, parameters.Take(2));
                context.SimulationPreparations.ExecuteTemperatureBehaviorBeforeLoad(resistor);

                context.SimulationPreparations.ExecuteActionBeforeSetup(
                    (simulation) =>
                {
                    if (context.ModelsRegistry is StochasticModelsRegistry stochasticModelsRegistry)
                    {
                        resistorModel = stochasticModelsRegistry.ProvideStochasticModel(name, simulation, vmodel);

                        if (!context.Result.FindObject(resistorModel.Name, out _))
                        {
                            stochasticModelsRegistry.RegisterModelInstance(resistorModel);
                            context.Result.Circuit.Add(resistorModel);
                        }
                    }

                    string resExpression =
                        $"table(v({parameters.Get(2)}, {parameters.Get(3)}), @{resistorModel.Name}[voff], @{resistorModel.Name}[roff] , @{resistorModel.Name}[von], @{resistorModel.Name}[ron])";
                    context.SetParameter(resistor, "resistance", resExpression, beforeTemperature: true, onload: true);
                });
                return(resistor);
            }
            else
            {
                VoltageSwitch vsw = new VoltageSwitch(name);
                context.CreateNodes(vsw, parameters);

                context.SimulationPreparations.ExecuteActionBeforeSetup((simulation) =>
                {
                    context.ModelsRegistry.SetModel(
                        vsw,
                        simulation,
                        parameters.Get(4),
                        $"Could not find model {parameters.Get(4)} for voltage switch {name}",
                        (VoltageSwitchModel model) => { vsw.Model = model.Name; },
                        context.Result);
                });

                // Optional ON or OFF
                if (parameters.Count == 6)
                {
                    switch (parameters.Get(5).Image.ToLower())
                    {
                    case "on":
                        vsw.ParameterSets.SetParameter("on");
                        break;

                    case "off":
                        vsw.ParameterSets.SetParameter("off");
                        break;

                    default:
                        context.Result.Validation.Add(new ValidationEntry(ValidationEntrySource.Reader, ValidationEntryLevel.Warning, "ON or OFF expected", parameters.LineInfo));
                        return(vsw);
                    }
                }
                else if (parameters.Count > 6)
                {
                    context.Result.Validation.Add(new ValidationEntry(ValidationEntrySource.Reader, ValidationEntryLevel.Warning, "Too many parameters for voltage switch", parameters.LineInfo));
                    return(vsw);
                }

                return(vsw);
            }
        }