44namespace SpiceSharpParser . IntegrationTests . Components
55{
66 /// <summary>
7- /// Integration tests for model selection based on L and W parameters with lmin, lmax, wmin, wmax constraints.
7+ /// Integration tests for model selection (binning) based on instance parameters
8+ /// and model selection parameters (e.g. lmin, lmax, wmin, wmax).
89 /// </summary>
910 public class ModelDimensionTests : BaseTests
1011 {
@@ -39,14 +40,14 @@ public void MosfetSelectsCorrectModelBasedOnLength()
3940 Assert . NotNull ( netlist ) ;
4041 Assert . False ( netlist . ValidationResult . HasError ) ;
4142
42- // Both MOSFETs should be created
43+ // M1 L=0.5u should match NMOS.0 (lmin=0.1u lmax=1u)
4344 var mosfet1 = netlist . Circuit [ "m1" ] as Mosfet1 ;
4445 Assert . NotNull ( mosfet1 ) ;
4546
47+ // M2 L=5u should match NMOS.1 (lmin=1u lmax=10u)
4648 var mosfet2 = netlist . Circuit [ "m2" ] as Mosfet1 ;
4749 Assert . NotNull ( mosfet2 ) ;
4850
49- // Verify models exist in circuit
5051 Assert . NotNull ( netlist . Circuit [ "NMOS.0" ] ) ;
5152 Assert . NotNull ( netlist . Circuit [ "NMOS.1" ] ) ;
5253 }
@@ -65,9 +66,11 @@ public void MosfetSelectsCorrectModelBasedOnWidth()
6566 Assert . NotNull ( netlist ) ;
6667 Assert . False ( netlist . ValidationResult . HasError ) ;
6768
69+ // M1 W=2u should match PMOS.0 (wmin=1u wmax=10u)
6870 var mosfet1 = netlist . Circuit [ "m1" ] as Mosfet1 ;
6971 Assert . NotNull ( mosfet1 ) ;
7072
73+ // M2 W=20u should match PMOS.1 (wmin=10u wmax=100u)
7174 var mosfet2 = netlist . Circuit [ "m2" ] as Mosfet1 ;
7275 Assert . NotNull ( mosfet2 ) ;
7376 }
@@ -86,18 +89,21 @@ public void MosfetSelectsCorrectModelBasedOnLengthAndWidth()
8689 Assert . NotNull ( netlist ) ;
8790 Assert . False ( netlist . ValidationResult . HasError ) ;
8891
92+ // M1 L=0.5u W=5u should match NMOS.0
8993 var mosfet1 = netlist . Circuit [ "m1" ] as Mosfet1 ;
9094 Assert . NotNull ( mosfet1 ) ;
9195
96+ // M2 L=5u W=50u should match NMOS.1
9297 var mosfet2 = netlist . Circuit [ "m2" ] as Mosfet1 ;
9398 Assert . NotNull ( mosfet2 ) ;
9499 }
95100
96101 [ Fact ]
97- public void MosfetFallsBackToDefaultModelWhenNoMatch ( )
102+ public void MosfetFallsBackToBaseModelWhenNoMatch ( )
98103 {
104+ // L=100u exceeds NMOS.0's lmax=1u, should fall back to base NMOS
99105 var netlist = GetSpiceSharpModel (
100- "MOSFET falls back to default model" ,
106+ "MOSFET falls back to base model" ,
101107 "M1 D G S B NMOS L=100u W=100u" ,
102108 ".model NMOS.0 NMOS level=1 lmin=0.1u lmax=1u" ,
103109 ".model NMOS NMOS level=1" ,
@@ -106,8 +112,8 @@ public void MosfetFallsBackToDefaultModelWhenNoMatch()
106112 Assert . NotNull ( netlist ) ;
107113 Assert . False ( netlist . ValidationResult . HasError ) ;
108114
109- var mosfet1 = netlist . Circuit [ "m1" ] as Mosfet1 ;
110- Assert . NotNull ( mosfet1 ) ;
115+ var mosfet = netlist . Circuit [ "m1" ] as Mosfet1 ;
116+ Assert . NotNull ( mosfet ) ;
111117 }
112118
113119 #endregion
@@ -151,10 +157,11 @@ public void ResistorSelectsCorrectModelBasedOnDimensions()
151157 }
152158
153159 [ Fact ]
154- public void ResistorWithOnlyLengthParameter ( )
160+ public void ResistorModelWithOnlyLengthConstraints ( )
155161 {
162+ // Models only constrain L (no wmin/wmax), so W is irrelevant for selection
156163 var netlist = GetSpiceSharpModel (
157- "Resistor with only L parameter " ,
164+ "Resistor model with only length constraints " ,
158165 "R1 1 0 RMOD L=0.5u W=1u" ,
159166 "R2 1 0 RMOD L=5u W=1u" ,
160167 ".model RMOD.0 R RSH=1 lmin=0.1u lmax=1u" ,
@@ -172,10 +179,11 @@ public void ResistorWithOnlyLengthParameter()
172179 }
173180
174181 [ Fact ]
175- public void ResistorWithOnlyWidthParameter ( )
182+ public void ResistorModelWithOnlyWidthConstraints ( )
176183 {
184+ // Models only constrain W (no lmin/lmax), so L is irrelevant for selection
177185 var netlist = GetSpiceSharpModel (
178- "Resistor with only W parameter " ,
186+ "Resistor model with only width constraints " ,
179187 "R1 1 0 RMOD L=1u W=5u" ,
180188 "R2 1 0 RMOD L=1u W=50u" ,
181189 ".model RMOD.0 R RSH=1 wmin=1u wmax=10u" ,
@@ -273,10 +281,11 @@ public void BJTSelectsCorrectModelBasedOnDimensions()
273281 }
274282
275283 [ Fact ]
276- public void BJTWithOnlyLengthParameter ( )
284+ public void BJTModelWithOnlyLengthConstraints ( )
277285 {
286+ // Models only constrain L, component has only L
278287 var netlist = GetSpiceSharpModel (
279- "BJT with only L parameter " ,
288+ "BJT model with only length constraints " ,
280289 "Q1 C B E QMOD L=0.5u" ,
281290 "Q2 C B E QMOD L=5u" ,
282291 ".model QMOD.0 NPN lmin=0.1u lmax=1u" ,
@@ -334,10 +343,11 @@ public void DiodeSelectsCorrectModelBasedOnDimensions()
334343 }
335344
336345 [ Fact ]
337- public void DiodeWithOnlyWidthParameter ( )
346+ public void DiodeModelWithOnlyWidthConstraints ( )
338347 {
348+ // Models only constrain W, component has only W
339349 var netlist = GetSpiceSharpModel (
340- "Diode with only W parameter " ,
350+ "Diode model with only width constraints " ,
341351 "D1 A K DMOD W=5u" ,
342352 "D2 A K DMOD W=50u" ,
343353 ".model DMOD.0 D wmin=1u wmax=10u" ,
@@ -395,10 +405,11 @@ public void JFETSelectsCorrectModelBasedOnDimensions()
395405 }
396406
397407 [ Fact ]
398- public void JFETWithOnlyLengthParameter ( )
408+ public void JFETModelWithOnlyLengthConstraints ( )
399409 {
410+ // Models only constrain L, component has only L
400411 var netlist = GetSpiceSharpModel (
401- "JFET with only L parameter " ,
412+ "JFET model with only length constraints " ,
402413 "J1 D G S JMOD L=0.5u" ,
403414 "J2 D G S JMOD L=5u" ,
404415 ".model JMOD.0 PJF lmin=0.1u lmax=1u" ,
@@ -488,6 +499,7 @@ public void ModelWithNonSequentialNumericSuffixes()
488499 [ Fact ]
489500 public void FallsBackToBaseModelWhenNoSuffixedModelMatches ( )
490501 {
502+ // L=100u exceeds both suffixed models' lmax, should fall back to base NMOS
491503 var netlist = GetSpiceSharpModel (
492504 "Falls back to base model when no suffixed model matches" ,
493505 "M1 D G S B NMOS L=100u W=100u" ,
@@ -550,10 +562,11 @@ public void ResistorSelectsModelWithNonNumericSuffix()
550562 #region Edge Cases
551563
552564 [ Fact ]
553- public void ComponentWithoutLWParametersUsesDefaultModel ( )
565+ public void MosfetWithoutLWParametersMatchesFirstSuffixedModel ( )
554566 {
567+ // Without L/W, predicate is null — first suffixed model is selected (not base model)
555568 var netlist = GetSpiceSharpModel (
556- "Component without L/W uses default " ,
569+ "MOSFET without L/W matches first suffixed model " ,
557570 "M1 D G S B NMOS" ,
558571 ".model NMOS.0 NMOS level=1 lmin=0.1u lmax=1u" ,
559572 ".model NMOS NMOS level=1" ,
@@ -569,6 +582,8 @@ public void ComponentWithoutLWParametersUsesDefaultModel()
569582 [ Fact ]
570583 public void ModelWithOnlyLminConstraint ( )
571584 {
585+ // RMOD.0 has lmin=1u: R1 L=0.5u fails (below min), falls back to base RMOD
586+ // R2 L=5u passes (above min), matches RMOD.0
572587 var netlist = GetSpiceSharpModel (
573588 "Model with only lmin constraint" ,
574589 "R1 1 0 RMOD L=0.5u W=1u" ,
@@ -590,6 +605,8 @@ public void ModelWithOnlyLminConstraint()
590605 [ Fact ]
591606 public void ModelWithOnlyLmaxConstraint ( )
592607 {
608+ // CMOD.0 has lmax=1u: C1 L=0.5u passes (below max), matches CMOD.0
609+ // C2 L=5u fails (above max), falls back to base CMOD
593610 var netlist = GetSpiceSharpModel (
594611 "Model with only lmax constraint" ,
595612 "C1 1 0 CMOD L=0.5u W=1u" ,
@@ -611,6 +628,8 @@ public void ModelWithOnlyLmaxConstraint()
611628 [ Fact ]
612629 public void ModelWithOnlyWminConstraint ( )
613630 {
631+ // NMOS.0 has wmin=1u: M1 W=0.5u fails (below min), falls back to base NMOS
632+ // M2 W=5u passes (above min), matches NMOS.0
614633 var netlist = GetSpiceSharpModel (
615634 "Model with only wmin constraint" ,
616635 "M1 D G S B NMOS L=1u W=0.5u" ,
@@ -632,6 +651,8 @@ public void ModelWithOnlyWminConstraint()
632651 [ Fact ]
633652 public void ModelWithOnlyWmaxConstraint ( )
634653 {
654+ // QMOD.0 has wmax=10u: Q1 W=5u passes (below max), matches QMOD.0
655+ // Q2 W=50u fails (above max), falls back to base QMOD
635656 var netlist = GetSpiceSharpModel (
636657 "Model with only wmax constraint" ,
637658 "Q1 C B E QMOD W=5u" ,
@@ -653,6 +674,7 @@ public void ModelWithOnlyWmaxConstraint()
653674 [ Fact ]
654675 public void MultipleModelsWithOverlappingRanges ( )
655676 {
677+ // D1 matches both DMOD.0 and DMOD.1; first match wins
656678 var netlist = GetSpiceSharpModel (
657679 "Multiple models with overlapping ranges" ,
658680 "D1 A K DMOD L=0.8u W=8u" ,
0 commit comments