Issue logging within an embedded C function

103 Views Asked by At

I'd like to generate logging messages from within a C function embedded in a DML method. Take the example code below where the fib() function is called from the write() method of the regs bank. The log methods available to C all require a pointer to the current device.

Is there a way to get the device that calls the embedded function? Do I need to pass the device pointer into fib()?

dml 1.2;
device simple_embedded;
parameter documentation = "Embedding C code example for"
    + " Model Builder User's Guide";
parameter desc = "example of C code";

extern int fib(int x);

bank regs {
    register r0 size 4 @0x0000 {
        parameter allocate = false;
        parameter configuration = "none";
        method write(val) {
            log "info": "Fibonacci(%d) = %d.", val, fib(val);
        }

        method read() -> (value) {
            // Must be implemented to compile            
        }
       
    }
}

header %{
int fib(int x);
%}

footer %{
int fib(int x) {
    SIM_LOG_INFO(1, mydev, 0, "Generating Fibonacci for %d", x); 
    if (x < 2) return 1;
    else return fib(x-1) + fib(x-2);
}
%}

I want to log from an embedded C function.

2

There are 2 best solutions below

2
jakobengblom2 On

I solved this by passing the Simics conf_object_t pointer along to C. Just like implied in the question.

So you would use:

int fib(conf_object_t *mydev, int x) {
    SIM_LOG_INFO(1, mydev, 0, "Generating Fibonacci for %d", x); 
}

And

        method write(val) {
            log "info": "Fibonacci(%d) = %d.", val, fib(dev.obj,val);
        }
0
Erik Carstensen On

Jakob's answer is the right one if your purpose is to offload some computations to C code (which makes sense in many situations, like when functionality is implemented by a lib).

However, if you just want a way to pass a callback to an API that asks for a function pointer, then it is easier to keep the implementation within DML and use a method reference, like:

method init() {
    SIM_add_notifier(obj, trigger_fib_notifier_type, obj, &trigger_fib,
                     &dev.regs.r0.val);
}

method trigger_fib(conf_object_t *_, lang_void *aux) {
    value = *cast(aux, uint64 *);
    local int result = fib(value);
    log info: "result: %d", result;
}

method fib(int x) -> (int) {
    log info: "Generating Fibonacci for %d", x; 
    if (x < 2) return 1;
    else return fib(x-1) + fib(x-2);
}