diff --git a/src/SpiceSharpParser.IntegrationTests/Examples/Circuits/MosfetExample2.cir b/src/SpiceSharpParser.IntegrationTests/Examples/Circuits/MosfetExample2.cir new file mode 100644 index 00000000..a60eeb02 --- /dev/null +++ b/src/SpiceSharpParser.IntegrationTests/Examples/Circuits/MosfetExample2.cir @@ -0,0 +1,4 @@ +Mosfet circuit +Md 0 1 2 3 my-pmos +.model my-pmos pmos(level = 3) +.END diff --git a/src/SpiceSharpParser.IntegrationTests/Examples/Extensions/CustomMosfetModelTest.cs b/src/SpiceSharpParser.IntegrationTests/Examples/Extensions/CustomMosfetModelTest.cs index 9cbda205..4be7dc64 100644 --- a/src/SpiceSharpParser.IntegrationTests/Examples/Extensions/CustomMosfetModelTest.cs +++ b/src/SpiceSharpParser.IntegrationTests/Examples/Extensions/CustomMosfetModelTest.cs @@ -1,4 +1,6 @@ -using System.IO; +using SpiceSharpParser.ModelReaders.Netlist.Spice.Readers.EntityGenerators.Components.Semiconductors; +using SpiceSharpParser.ModelReaders.Netlist.Spice.Readers.EntityGenerators.Models; +using System.IO; using Xunit; namespace SpiceSharpParser.IntegrationTests.Examples.Extensions @@ -19,6 +21,34 @@ public void When_CustomMosfetModel_Used_NoExceptions() var spiceSharpReader = new SpiceSharpReader(); spiceSharpReader.Settings.CaseSensitivity.IsModelTypeCaseSensitive = false; spiceSharpReader.Settings.Mappings.Models.Map(new[] { "PMOS", "NMOS" }, new CustomMosfetModelGenerator()); + var spiceSharpModel = spiceSharpReader.Read(parseResult.FinalModel); + + Assert.False(spiceSharpModel.ValidationResult.HasError); + Assert.False(spiceSharpModel.ValidationResult.HasWarning); + } + [Fact] + public void When_CustomMosfetModel2_Used_NoExceptions() + { + // Create a model from text file + string path = Path.Combine(Directory.GetCurrentDirectory(), "Examples/Circuits/MosfetExample2.cir"); + var netlistContent = File.ReadAllText(path); + var parser = new SpiceNetlistParser(); + parser.Settings.Lexing.HasTitle = true; + var parseResult = parser.ParseNetlist(netlistContent); + + // Convert to Spice# + var spiceSharpReader = new SpiceSharpReader(); + spiceSharpReader.Settings.CaseSensitivity.IsModelTypeCaseSensitive = false; + + // custom mosfet models + var modelGenerator = new MosfetModelGenerator(); + modelGenerator.AddLevel(4); + spiceSharpReader.Settings.Mappings.Models.Map(new[] { "PMOS", "NMOS" }, modelGenerator); + var mosfetGenerator = new MosfetGenerator(); + mosfetGenerator.AddMosfet(); + spiceSharpReader.Settings.Mappings.Components.Map("M", mosfetGenerator); + + var spiceSharpModel = spiceSharpReader.Read(parseResult.FinalModel); Assert.False(spiceSharpModel.ValidationResult.HasError); diff --git a/src/SpiceSharpParser.IntegrationTests/SpiceSharpParser.IntegrationTests.csproj b/src/SpiceSharpParser.IntegrationTests/SpiceSharpParser.IntegrationTests.csproj index 9bad3f35..ab22d991 100644 --- a/src/SpiceSharpParser.IntegrationTests/SpiceSharpParser.IntegrationTests.csproj +++ b/src/SpiceSharpParser.IntegrationTests/SpiceSharpParser.IntegrationTests.csproj @@ -96,6 +96,9 @@ Always + + Always + Always diff --git a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/EntityGenerators/Components/Semiconductors/MosfetGenerator.cs b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/EntityGenerators/Components/Semiconductors/MosfetGenerator.cs index 474dc50d..3be4c2fc 100644 --- a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/EntityGenerators/Components/Semiconductors/MosfetGenerator.cs +++ b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/EntityGenerators/Components/Semiconductors/MosfetGenerator.cs @@ -37,6 +37,16 @@ public MosfetGenerator() protected Dictionary> Mosfets { get; } = new (); + public void AddMosfet() + where TMosfet : SpiceSharp.Components.Component + { + Mosfets[typeof(TModel)] = (name) => + { + var mosfet = (TMosfet)Activator.CreateInstance(typeof(TMosfet), name); + return new MosfetDetails { Mosfet = mosfet, SetModelAction = (model) => mosfet.Model = model.Name }; + }; + } + public override IEntity Generate(string componentIdentifier, string originalName, string type, ParameterCollection parameters, IReadingContext context) { // Errors diff --git a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/EntityGenerators/Models/MosfetModelGenerator.cs b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/EntityGenerators/Models/MosfetModelGenerator.cs index d4e13ef5..ffe5967c 100644 --- a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/EntityGenerators/Models/MosfetModelGenerator.cs +++ b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/EntityGenerators/Models/MosfetModelGenerator.cs @@ -1,6 +1,9 @@ using System; using System.Collections.Generic; +using SpiceSharp; using SpiceSharp.Components; +using SpiceSharp.Components.Mosfets; +using SpiceSharp.Entities; using SpiceSharpParser.Common.Validation; using SpiceSharpParser.ModelReaders.Netlist.Spice.Context; using SpiceSharpParser.Models.Netlist.Spice.Objects; @@ -56,6 +59,23 @@ public MosfetModelGenerator() /// protected Dictionary> Levels { get; } = new Dictionary>(); + public void AddLevel(int level) + where TModel : Entity + where TParameters : ModelParameters, ICloneable, new() + { + Levels[level] = (name, type, _) => + { + var mosfet = (TModel)Activator.CreateInstance(typeof(TModel), name); + switch (type.ToLower()) + { + case "nmos": mosfet.SetParameter("nmos", true); break; + case "pmos": mosfet.SetParameter("pmos", true); break; + } + + return new Context.Models.Model(name, mosfet, mosfet.Parameters); + }; + } + public override Context.Models.Model Generate(string id, string type, ParameterCollection parameters, IReadingContext context) { var clonedParameters = (ParameterCollection)parameters.Clone();