Adding Verilog A CNTFET Compact Model

273 views
Skip to first unread message

joaquimprad...@gmail.com

unread,
Jul 10, 2015, 8:41:42 PM7/10/15
to xyce-...@googlegroups.com
Hello,
I don't know if anyone has done this yet, but I'm trying to add the model provided at https://nanohub.org/publications/42 for a CNTFET, for some experimentation. However, I keep running into some errors with adms, while trying to follow the instructions provided at the xyce documentation. Can someone with more experience help me with this?
Thank you in advance,
Joaquim Prado

xyce-users

unread,
Jul 10, 2015, 10:02:11 PM7/10/15
to xyce-...@googlegroups.com, joaquimprad...@gmail.com

I don't think anyone has added that particular model yet --- the Xyce team hasn't.

What errors are you getting from ADMS?  It may be that there is a simple fix or work-around.   Please post details and I'll help if I can.

On the other hand, often we find a new model that exposes gaps in the Xyce/ADMS back-end, requiring extra work to support language elements that we hadn't implemented yet.  That could be the case here, too.   Hard to say without knowing what errors you're getting.

joaquimprad...@gmail.com

unread,
Jul 11, 2015, 10:27:08 AM7/11/15
to xyce-...@googlegroups.com, xyce-...@googlegroups.com
First, thank you for the quick reply!
About the errors, it seems that when i try to process the vscnfet_1_0_1.va ,without modification, with admsXml it gives me:

[info...] admsXml-2.3.4 (1a5c569) Mar 30 2015 16:17:33
[fatal..] ./vscnfet_1_0_1.va: during lexical analysis syntax error at line 93 -- see '['


I took a look at that line, and it seems that problem points to the specifications of the range of values pf the form : real Evh[0:1]
So, naturally, I tried removing the range to see if i could get the adms script to at least run without errors, but then I receive the following:

[info...] admsXml-2.3.4 (1a5c569) Mar 30 2015 16:17:33
[error..] [~/Xyce-6.2/utils/ADMS/xyceBasicTemplates.xml:2417]: 'probe' bad attribute
[error..] [~/Xyce-6.2/utils/ADMS/xyceBasicTemplates.xml:2433]: 'probe' bad attribute
[fatal..] Template not found:
[fatal..]   <admst:template match="array"/>
[fatal..]   see:  [~/Xyce-6.2/utils/ADMS/xyceBasicTemplates.xml:2200]


I'm anexing the unmodified .va, as that may be useful.

Needless to say, I'm new to this, so not quite sure how to proceed here. Any help is appreciated.
vscnfet_1_0_1.va

xyce-users

unread,
Jul 11, 2015, 11:20:15 AM7/11/15
to xyce-...@googlegroups.com, joaquimprad...@gmail.com
Sorry to say, it looks like the vscnfet verilog uses a feature of verilog that we hadn't implemented in our back end.  That is, we did not implement support for verilog-a arrays. The errors you're seeing are all related to that, where ADMS is trying to call a template that we haven't implemented.   The template is required to tell ADMS how to emit C++ code for array references.

I do not think it will be particularly difficult or time-consuming for us to implement the array template, and doing so would be in keeping with the Xyce projects plan to improve the back end by adding more features to support NEEDs compact models.  But the pace of development on the ADMS back end is slow, and it will be at least release 6.4 before we could make it available (Xyce 6.3 is already complete and should be released any time now, as soon as DOE approves the copyright assertion).

As if that weren't bad enough, it also seems that ADMS itself is having trouble parsing the array declaration on line 93.  So before we could do anything in the Xyce part of the process, we'd have to get the ADMS developers to add the essential parser changes to get past that.  This lack can't be very deep, because ADMS already knows enough about array syntax to recognize the uses of E[...] elsewhere in the verilog input and try to call the nonexistent array template in our back-end.  It might be worth opening a request for that at the official ADMS issue tracker on github.   That repository is at https://github.com/Qucs/ADMS .  

If you can get the ADMS authorsto fix whatever issue is blocking parsing of line 93 of the input, then I might be able to help with the missing array template without having you wait for the next release of Xyce.  I believe that template will be extremely easy to write.  But there's no point in doing it if ADMS itself won't even accept the declaration of the array.  One of the ADMS maintainers is subscribed to this mailing list, and he may be able to chime in here with more information.

Thomas Russo

unread,
Jul 11, 2015, 12:02:41 PM7/11/15
to xyce-...@googlegroups.com, xyce-...@googlegroups.com, joaquimprad...@gmail.com
All this said, it may be a simple workaround to get this model into Xyce if you are willing to hack simply on the verilog input.

The sole use of arrays in this model is so trivial that it could be done just as easily without arrays.  It is being used just to select one of two values in a loop that runs over two values.  Could be done just as easily with a ternary operator and no array.  Try modifying the CarrierDensity analog function, which in the original is:

    analog function real CarrierDensity;
        input Eg, Ef;  // Ef is the Fermi level w.r.t. Efi
        real Eg, Ef;
        real Evh[0:1], x, n1, n2, a0, a1, del, fsmo, n, n0, d2_E2, P_1_vt;
        integer i;
        begin
            n0     = 1.9926e9; // n0 = 8/3/pi/acc/Vp;
            n      = 0;
            P_1_vt = 1/$vt;
            Evh[0] = Eg/2;
            Evh[1] = Eg;
            for (i = 0;i<2;i = i+1) begin
                x     = exp((Evh[i]-Ef)*P_1_vt);
                n1    = n0*sqrt(`M_PI*$vt/2*Evh[i])/x;
                a0    = 1/(1+x);
                a1    = -x*P_1_vt/((1+x)*(1+x));
                del   = Ef + $vt*ln(1+x);
                d2_E2 = sqrt(del*del-Evh[i]*Evh[i]);
                n2    = n0*((a1/2*del+a0-a1*Evh[i])*d2_E2+a1/2*Evh[i]*Evh[i]*ln((del+d2_E2)/Evh[i]));
                fsmo  = 1/(1+pow(x,-1.3));
                n     = n + (n1*fsmo + n2*(1-fsmo));
            end
            CarrierDensity = n;
        end
    endfunction  // CarrierDensity

If this were rewritten:
    analog function real CarrierDensity;
        input Eg, Ef;  // Ef is the Fermi level w.r.t. Efi
        real Eg, Ef;
        real Evhkludge, x, n1, n2, a0, a1, del, fsmo, n, n0, d2_E2, P_1_vt;
        integer i;
        begin
            n0     = 1.9926e9; // n0 = 8/3/pi/acc/Vp;
            n      = 0;
            P_1_vt = 1/$vt;
             for (i = 0;i<2;i = i+1) begin
                Evhkludge = (i==0)?Eg/2:Eg;
                x     = exp((Evhkludge-Ef)*P_1_vt);
                n1    = n0*sqrt(`M_PI*$vt/2*Evhkludge)/x;
                a0    = 1/(1+x);
                a1    = -x*P_1_vt/((1+x)*(1+x));
                del   = Ef + $vt*ln(1+x);
                d2_E2 = sqrt(del*del-Evhkludge*Evhkludge);
                n2    = n0*((a1/2*del+a0-a1*Evhkludge)*d2_E2+a1/2*Evhkludge*Evhkludge*ln((del+d2_E2)/Evhkludge));
                fsmo  = 1/(1+pow(x,-1.3));
                n     = n + (n1*fsmo + n2*(1-fsmo));
            end
            CarrierDensity = n;
        end
    endfunction  // CarrierDensity

then it should generate code that does exactly the same thing as the other, without any use of arrays.  This might get you to the point of being able to do your work as quickly as possible.

xyce-users

unread,
Jul 11, 2015, 12:06:45 PM7/11/15
to xyce-...@googlegroups.com, tom....@gmail.com, joaquimprad...@gmail.com

The use of ternary operator might throw an error in the Xyce-6.2 version, if Eg is probe-dependent (a long-standing bug in the Xyce ADMS back-end that has been fixed in 6.3).  If it does, instead of doing
  Evhkludge = (i==0)?Eg/2:Eg;
just do
  Evhkludge=Eg;
  if (i==0)
    Evhkludge=Eg/2;

joaquimprad...@gmail.com

unread,
Jul 11, 2015, 5:58:57 PM7/11/15
to xyce-...@googlegroups.com, tom....@gmail.com, xyce-...@googlegroups.com
    I've modified the source as  thomas suggested, and it seems to have passed the adms stage but when I try to recompile xyce it gives some errors. I've attached the modified  verilog source ,the files generated by admsXml and the build log.
    From what i gathered some of the errors seem to be relative to the scope of adms_vt_nom (I'm not sure why because it seems from the source the definition would be handled internally?), the others to the templates not being able to match the function arguments required.
N_DEV_ADMSvscnfet_1_0_1.h
N_DEV_ADMSvscnfet_1_0_1.C
vscnfet_1_0_1.va
mylog.txt

xyce-users

unread,
Jul 11, 2015, 7:15:33 PM7/11/15
to xyce-...@googlegroups.com, joaquimprad...@gmail.com, tom....@gmail.com
Joaquim:

Yes, the Xyce/ADMS handling of analog functions is a bit broken, and we've encountered models that it doesn't handle properly.  The problem is coming up with a templating method that works universally --- the one we have works for all of the models we've encountered so far, with the exception of the FBH HBT model.  This one required extensive manual hacking of the generated C++ to get it to work, and I never worked out how to change the back-end to generate the right templating so that it would always work.  Right now, it assumes that all arguments and the return value of the analog function are of the same type, or can automatically be converted to the same type at compile time.  If some arguments of the function have probe-independent value, and others have probe dependence, this is wrong.  It's due to the use of Sacado (automatic differentiation) data types for variables with probe dependence.  Use of Sacado vastly simplifies our ADMS back-end, because it doesn't need to do any work differentiating expressions.  But use of these complex types makes it much harder to generate universally correct code for all input verilog.

If you look in the Xyce source tree, under utils/ADMS/examples/fbh-hbt-2.1 you'll see a couple of patch files that do this post-processing of the analog functions.  It is ugly.  But far less ugly than what it would take to get it right in the ADMST language.  This is what is eluded to by the statements under the heading "The Xyce/ADMS capability is a work in progress" on the web site documentation of the capability.

adms_vt_nom is defined as a private variable in the instance class, which means that as soon as an analog function tries to access it, the scheme is broken.  It may be necessary to move the declaration of the adms_vt_nom variable so it's outside of instance scope, or hack the generated C++ to pass in the instance-scoped variable into the function directly.  This, too, is ugly.  Alternatively, you could modify each of the analog functions that use "$vt" to take an additional "vt" argument, and then change all the calls of those functions to include "$vt" in the argument list.

At this point, your only path forward is to modify the generated code to make it compile.  This will generally involve adding additional types to the template for the analog functions, and sometimes changes to the calls of those analog functions to help the compiler work out I am sorry that this is the case, but the ADMS back-end for Xyce is really a work in (slow) progress, and cannot get everything right yet, especially with complicated analog functions.  The patch file in the fbh-hbt-2.1 directory can show you some of the things we had to do to make that model work.

I managed to simplify *some* of the analog function handling in the soon-to-be-released Xyce 6.3, but it still leaves much to be desired, as this model reveals.  Even the 6.3 version of our ADMS back-end probably won't handle this model well without human post-processing.

joaquimprad...@gmail.com

unread,
Jul 12, 2015, 11:37:24 AM7/12/15
to xyce-...@googlegroups.com, tom....@gmail.com, xyce-...@googlegroups.com

Thank you for the fast reply,
I have modified the original code just to get it to compile, and it seems to get through , however i'm having some difficulty when i try to make the device be recognized as a type N or P channel device, as well as a 'MOSFET' device, maybe I'm going the wrong way about this? I anexed 2 versions... the  first one gets through the compilation process but has no mention of the device type in the c++ generated.
vscnfet_1_0_1_compiling.va
vscnfet_1_0_1_hacked.va

xyce-users

unread,
Jul 12, 2015, 4:11:44 PM7/12/15
to xyce-...@googlegroups.com, joaquimprad...@gmail.com
In order to make your device a MOSFET you'll need to add xyceModelGroup="MOSFET" (as you have in the "hacked" verilog file) and  set xyceLevelNumber to an *unused* mosfet model level number in the "attr" line.  Setting xyceModelGroup="MOSFET" makes it accessible as an "M" device in the netlist, and lets you associate an NMOS or PMOS model card with each instance.   Don't use commas to separate attributes.

module vscnfet_1_0_1(D,G,S) `attr(xyceModelGroup="MOSFET"  xyceSpiceDeviceName="CNTFET"  xyceLevelNumber="123");

This will allow you to specify your device in a netlist using an NMOS or PMOS model card with level=123.  You can't use "1" here, because there's already a level 1 mosfet (the standard SPICE level 1).  You need to use a level number that is not already in use by another MOSFET.  There is no upper bound on the value used here other than that it must be able to be stored in a C++ "int" variable.

Unfortunately, the Xyce ADMS back-end does not automatically any code in the model constructor to set a variable that differentiates NMOS from PMOS based on which model card type you use.  This is because every device names this variable something different.  Some call it TYPE, some call it type, and still others pick something completely different like "devsign" (the BSIM6 does that).  I have even seen one model that calls it "gender."  In your case, the variable is called FETtype.  Since we can't guess what variable the model uses to set the type, we don't try to do anything automatically, and you must do it in a post-processing step on the generated C++ code.

Take a look at the patch files in the utils/ADMS/examples/bsimcmg*, and psp* directories (and when Xyce 6.3 is released, the bsim6), and you'll see that they all have patches that add a device-specific block that sets the internal variable used by those devices for NMOS vs. PMOS.  You will need to do the same thing in your device's generated C++ Model::Model(....) function.

The code you have to add will look something like this (taken from the PSP example, see src/DeviceModelPKG/ADMS/src/N_DEV_PSP103VA.C, and the associated patch file in utils/ADMS/examples/psp103/make_psp_usable.diff):

  // Manually added code:
  if (getType() == "pmos" || getType() == "PMOS")
    TYPE = -1;

This appears between the "updateDependentParams()" and "processParams()" call of the model constructor (Model::Model(...)).  So if you do the same thing in your own output .C file (substituting FETtype for TYPE), you'll be able to select NMOS vs. PMOS just by using an NMOS or PMOS model card.

Alternatively, if you skip this manual hack, you'll have to specify "FETtype=-1" in the model card (even if it's a PMOS card). 

These annoying hand-hacking things are aspects I'd ultimately like to get rid of from our back-end, but so far I've not worked out a clean way to do it.  If you look at other codes that use ADMS, they have some hard-coded tricks that are specific for known models (e.g., they'll have a block that recognizes  the input verilog as being FBH_HBT code, and do something special for it -- some of these back-ends even refuse to process input verilog that isn't in a hard-coded enumerated set).  We didn't want to go there and make our back-end so limited, but the result is that it leaves a little post-processing work for the person trying to get a new model into the code.  I personally find the hand-coding of this pre-processing step much less painful than trying to band-aid the ADMS back-end to automate it.

Our development of the ADMS back-end in Xyce happens in fits and spurts, with only enough work being put into the XML back-end in each new release of Xyce to get a set of new models into the code with a minimum of hand-hacking.  Once we figure out what that minimum bit of hand-hacking is, we create a patch file that can be applied to ADMS's output to recreate the usable version reliably.  This is why every non-trivial device in the utils/ADMS/examples has a little script called "make_xxxx_usable.sh".
,

joaquimprad...@gmail.com

unread,
Jul 13, 2015, 1:39:17 AM7/13/15
to xyce-...@googlegroups.com, xyce-...@googlegroups.com
I have attempted what you said...and it seems now i get errors in convergence ,even with simple dc sweeping.  I made a small adaptation to one of the netlists on the regression suite, to attempt test the model. I tried to make as few parameters changeable as possible at first but it seems something is now causing the solver iterations to fail it seems......any ideas?
I thank you for taking the time to answer these questions, if nothing else, it's been very insightful to get this kind of feedback!
N_DEV_ADMSvscnfet_1_0_1.C
N_DEV_ADMSvscnfet_1_0_1.h
nmos6_dc.cir
vscnfet_1_0_1_hacked_mosified.va

xyce-users

unread,
Jul 13, 2015, 7:15:34 PM7/13/15
to xyce-...@googlegroups.com, joaquimprad...@gmail.com
Joaquim:

Unfortunately, convergence failures when trying out new MOSFET models are not very surprising.  The default build of Xyce does not provide you with very much information you can use to diagnose such problems, and you'll want to reconfigure with "--enable-verbose_nonlinear" (at a minimum), then do a "make clean" and rebuild.  This will cause Xyce to emit information at every nonlinear solver iteration to show you what is actually happening internally.

One thing to look for is to see if the residual printed in each iteration is blowing up or if it's just getting small but not really converging completely.  The former is often a problem when using devices that should have voltage limiting applied (a whole new can of worms).

Without a good set of example parameters and a known-good test harness for this specific device, it's going to be difficult to determine if the problem is with the model itself, the test case, or Xyce.  You might want to contact the authors of the model and see if they can recommend a good combination of parameters and test-harness that is known to work in another simulator before proceeding.

xyce-users

unread,
Jul 13, 2015, 7:25:17 PM7/13/15
to xyce-...@googlegroups.com
Actually, you're probably better off using the parameter set on the nanohub page you posted at the beginning of this thread, and adapting some of the benchmark tests there for Xyce use.  This would probably get you closer to a good test case than trying to adapt the Xyce MOS Level 6 test case.  From what I can tell, these devices are meant to be running at very low voltages, and it is possible that you're trying to operate the model outside of the range where it is meant to perform well.  Though it is still possible that other issues are getting in the way of convergence, it is better to start with something that the authors say should work for the model.
Reply all
Reply to author
Forward
0 new messages