Quantcast
Channel: Cadence Functional Verification
Viewing all articles
Browse latest Browse all 652

Function Level C Interface – New C Interface for Specman

$
0
0

Working with the conventional Specman C language interface has two major disadvantages:

1.       There is a tight dependency between the e code and the C code. The user must include the Specman header file which was generated based on the e code. Every minor change in the e code requires regeneration of the header file.

2.       The C interface doesn't support calling e TCMs (Time Consuming Methods) from C code.

Let's take a look at the following C interface example:

<' //top.e

struct packet { ... };

unit u { 

    send(p:packet) is dynamic C routine libtest.so:;

    update()@sys.any is {

        wait [10];
        message(LOW,"[e] update after waiting 10 cycles");
        //do something

    };

    main_thread()@sys.any is {

        gen p; //a packet
        send(p);
        stop_run();

    };
};

C export u.update();

'>

In the above example we show the send() method which is implemented in C and therefore defined as dynamic C routine. update() is exported so you can call it from C code.  

The C code then implements send() and calls update() with SN_DISPATCH:

/* test.c */
#include "sn_top.h"
#include <stdio.h>

void send(SN_TYPE(u) me, SN_TYPE(packet) p) {

  /* Do something */
  SN_DISPATCH(update,me,u,(me));

}

This simple example illustrates the two disadvantages we mentioned earlier:

1.       Tight dependency - sn_top.h which is included in the C code must be regenerated each time the e code is changed no matter what the change was. Of course, regenerating the header enforces recompilation of the C code...

2.        Calling TCMs - update() is a TCM, "The run-time behavior of a TCM called from C is undefined" (quoted from Specman docs). Trying to run the example above will give an OS11 error. Undefined indeed...

The new Function Level C interface addresses those issues. Let's take a look in the following modified example:

unit u {

    //send(p:packet) is dynamic C routine libtest.so:; old declaration
    send(p:packet)@sys.any is import C libtest.so:;

};

//C export u.update(); old declaration
export C u.update();

As you can see, the e code remains the same but we changed the way we export and import the functions. Please note that send() was changed to be a TCM; this way we can call update() TCM from the C code.

And the new C code looks like:

#include "sn_fli_top.h"
#include "e_func_intf_user.h"
#include <stdio.h>

void send(eStructHandle me, eStructHandle p) {

  /* Do something */
  update(me);

}

You might want to pay attention to the following:

  • We use a header file sn_fli_top.h which is a generated header file, but in this case we need to generate a new file only if we change one of the export or import prototypes.
  • Structs and lists parameters are passed as handles (eStructHandle or eListHandle).
  • e_func_intf_user.h contains some auxiliary routines to take care of the handles. For example, to get or to set an item of a list. This file resides in Specman installation directory.
  • We call update() directly, SN_DISPATCH and other C interface macros are not needed anymore. Note that the first argument is the instance which routes the call.

How to generate the new header file? Which auxiliary routines does e_func_intf_user.h define?  What about save-restore flow?  You can get the answers to these questions and more details in Specman documentation.

Enjoy,

Nir Hadaya

Specman R&D 


Viewing all articles
Browse latest Browse all 652

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>