diff --git a/src/SpiceSharpParser.IntegrationTests/Examples/Circuits/MosfetExample3.cir b/src/SpiceSharpParser.IntegrationTests/Examples/Circuits/MosfetExample3.cir
new file mode 100644
index 00000000..cae39dda
--- /dev/null
+++ b/src/SpiceSharpParser.IntegrationTests/Examples/Circuits/MosfetExample3.cir
@@ -0,0 +1,5 @@
+Mosfet circuit
+Md 0 1 2 3 my-pmos
+.model my-pmos.1 pmos(level = 49 lmin=0.18u)
+.model my-pmos.2 pmos(level = 49 lmin=1.18u)
+.END
diff --git a/src/SpiceSharpParser.IntegrationTests/Examples/Extensions/Aggregate.cs b/src/SpiceSharpParser.IntegrationTests/Examples/Extensions/Aggregate.cs
new file mode 100644
index 00000000..71dab453
--- /dev/null
+++ b/src/SpiceSharpParser.IntegrationTests/Examples/Extensions/Aggregate.cs
@@ -0,0 +1,48 @@
+using SpiceSharp.Components;
+using SpiceSharp.Entities;
+using SpiceSharp.Simulations;
+using System.Collections.Generic;
+using System.Xml.Linq;
+
+public class BSIM3AggregateModel : Entity
+{
+ ///
+ /// Gets the models in the aggregate model based on sizes.
+ ///
+ public HashSet Models { get; } = [];
+
+ ///
+ /// Creates an aggregate model.
+ ///
+ /// The name.
+ public BSIM3AggregateModel(string name)
+ : base(name)
+ {
+ }
+
+ ///
+ /// Creates an aggregate model based on sizes.
+ ///
+ ///
+ ///
+ public BSIM3AggregateModel(string name, IEnumerable models)
+ : base(name)
+ {
+ foreach (var model in models)
+ Models.Add(model);
+ }
+
+ public override void CreateBehaviors(ISimulation simulation)
+ {
+ throw new System.NotImplementedException();
+ }
+
+ ///
+ public override IEntity Clone()
+ {
+ var n = new BSIM3AggregateModel(Name);
+ foreach (var model in Models)
+ n.Models.Add((BSIM3Model)model.Clone());
+ return n;
+ }
+}
\ No newline at end of file
diff --git a/src/SpiceSharpParser.IntegrationTests/Examples/Extensions/ComplexMosfetModelGenerator.cs b/src/SpiceSharpParser.IntegrationTests/Examples/Extensions/ComplexMosfetModelGenerator.cs
new file mode 100644
index 00000000..57ea5929
--- /dev/null
+++ b/src/SpiceSharpParser.IntegrationTests/Examples/Extensions/ComplexMosfetModelGenerator.cs
@@ -0,0 +1,43 @@
+using SpiceSharp.Components;
+using SpiceSharpParser.ModelReaders.Netlist.Spice.Context.Models;
+
+namespace SpiceSharpParser.ModelReaders.Netlist.Spice.Readers.EntityGenerators.Models
+{
+ public class ComplexMosfetModelGenerator : MosfetModelGenerator, ICustomModelGenerator
+ {
+ public ComplexMosfetModelGenerator()
+ {
+ }
+
+ public Context.Models.Model Process(Context.Models.Model model, IModelsRegistry models)
+ {
+
+ if (model.Entity is BSIM3Model bsim3Model)
+ {
+
+ if (model.Name.Contains("."))
+ {
+ var aggregateName = bsim3Model.Name.Substring(0, bsim3Model.Name.IndexOf('.'));
+ var aggregate = models.FindModel(aggregateName);
+ if (aggregate != null)
+ {
+ var aggrategeEntity = aggregate.Entity as BSIM3AggregateModel;
+ aggrategeEntity.Models.Add(bsim3Model);
+
+ return aggregate;
+ }
+ else
+ {
+ var aggrategeEntity = new BSIM3AggregateModel(aggregateName);
+ aggrategeEntity.Models.Add(bsim3Model);
+
+ return new Context.Models.Model(aggregateName, aggrategeEntity, null);
+ }
+
+ }
+
+ }
+ return model;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/SpiceSharpParser.IntegrationTests/Examples/Extensions/CustomMosfetModelTest.cs b/src/SpiceSharpParser.IntegrationTests/Examples/Extensions/CustomMosfetModelTest.cs
index ed0a7c82..6204284c 100644
--- a/src/SpiceSharpParser.IntegrationTests/Examples/Extensions/CustomMosfetModelTest.cs
+++ b/src/SpiceSharpParser.IntegrationTests/Examples/Extensions/CustomMosfetModelTest.cs
@@ -80,6 +80,36 @@ public void When_BSIM1_Used_NoExceptions()
spiceSharpReader.Settings.Mappings.Components.Map("M", mosfetGenerator);
+ var spiceSharpModel = spiceSharpReader.Read(parseResult.FinalModel);
+
+ Assert.False(spiceSharpModel.ValidationResult.HasError);
+ Assert.False(spiceSharpModel.ValidationResult.HasWarning);
+ }
+
+ [Fact]
+ public void When_BSIM3_Used_NoExceptions()
+ {
+ // Create a model from text file
+ string path = Path.Combine(Directory.GetCurrentDirectory(), "Examples/Circuits/MosfetExample3.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 ComplexMosfetModelGenerator();
+ modelGenerator.AddGenericLevel(49);
+
+ 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 95097b93..2b1b40db 100644
--- a/src/SpiceSharpParser.IntegrationTests/SpiceSharpParser.IntegrationTests.csproj
+++ b/src/SpiceSharpParser.IntegrationTests/SpiceSharpParser.IntegrationTests.csproj
@@ -97,6 +97,9 @@
Always
+
+ Always
+
Always
diff --git a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/EntityGenerators/IModelGenerator.cs b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/EntityGenerators/IModelGenerator.cs
index 37544c3f..4c4dcff9 100644
--- a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/EntityGenerators/IModelGenerator.cs
+++ b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/EntityGenerators/IModelGenerator.cs
@@ -7,4 +7,9 @@ public interface IModelGenerator
{
Model Generate(string id, string type, SpiceSharpParser.Models.Netlist.Spice.Objects.ParameterCollection parameters, IReadingContext context);
}
+
+ public interface ICustomModelGenerator : IModelGenerator
+ {
+ Context.Models.Model Process(Context.Models.Model model, IModelsRegistry models);
+ }
}
\ No newline at end of file
diff --git a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/EntityGenerators/StochasticModelsGenerator.cs b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/EntityGenerators/StochasticModelsGenerator.cs
index dbea6bfe..5d1af38a 100644
--- a/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/EntityGenerators/StochasticModelsGenerator.cs
+++ b/src/SpiceSharpParser/ModelReaders/Netlist/Spice/Readers/EntityGenerators/StochasticModelsGenerator.cs
@@ -82,8 +82,18 @@ public Context.Models.Model GenerateModel(IModelGenerator modelGenerator, string
RegisterDevAndLotModels(parameters, stochasticModelRegistry, model, (modelId) =>
{
var stochasticCandidate = modelGenerator.Generate(modelId, type, filteredParameters, context);
- context.ModelsRegistry.RegisterModelInstance(stochasticCandidate);
- return stochasticCandidate;
+
+ if (modelGenerator is ICustomModelGenerator custom)
+ {
+ var model = custom.Process(stochasticCandidate, context.ModelsRegistry);
+ context.ModelsRegistry.RegisterModelInstance(model);
+ return model;
+ }
+ else
+ {
+ context.ModelsRegistry.RegisterModelInstance(stochasticCandidate);
+ return stochasticCandidate;
+ }
});
return model;
}