how to get details about an "Environment call from M-mode" exception for ecall handler? - exception

we are integrating a new core (from pulpino to cv32).
I have no issues compiling and running code on my target, except when calling time() or srand() or rand() (but not div() for instance), where the default exception handler is called back and I have the following CSR values:
mcause : 0x0000000b
mstatus : 0x00001880 (mstatus.MPP : 03, mstatus.MIE : 01)
mepc : 0x00003476
mtval : 0x00000000
mip : 0x00000000
mie : 0xffff0000
misa : 0x40101104
I compiled and ran a very simple test (which is just/only a call to rand() that triggers the exception)
and then I display the CSR in the default exception handler with printfs.
as you can see, mcause = 0xB which is "Environment call from M-mode" (see p29)
The ECALL instruction is used to make a request to a higher privilege level. The binary interface
to the execution environment will define how parameters for the request are passed, but usually
these will be in defined locations in the integer register file. Executing an ECALL instruction causes
an Environment Call exception.
What I understand that ecall is used to call for instance linux.
and by disassembling the binary, I found that ecall was called in the time and rand functions, but not the div.
This proves that the ecall is triggering the exception.
1/ What could explain that ecall triggers an exception?
Executing an ECALL instruction causes
an Environment Call exception.
OK, so I guess I should be handling the ecall exception, but how?
here is my crt0.S:
.section .vectors, "ax"
.option norvc;
.global intvec
intvec:
.org 0x00
jal x0, default_exception_handler_c
[...]
.org 0x88
jal x0, ecall_insn_handler
2/ Why the ecall triggers the default_exception_handler_c and not the ecall_insn_handler? bad hw wiring?
details:
I am working with the riscv COREV toolchain configured with:
riscv32-corev-elf-gcc -v
[...]
Target: riscv32-corev-elf
Configured with: ../../gcc/configure --target=riscv32-corev-elf --prefix=/build/workspace/corev-gcc-centos7/install --with-sysroot=/build/workspace/corev-gcc-centos7/install/riscv32-corev-elf --with-native-system-header-dir=/include --with-newlib --disable-shared --enable-languages=c,c++ --enable-tls --disable-werror --disable-libmudflap --disable-libssp --disable-quadmath --disable-libgomp --disable-nls --enable-multilib --with-arch=rv32imac --with-abi=ilp32 --with-bugurl=''\''https://www.embecosm.com'\''' --with-pkgversion=''\''corev-openhw-gcc-centos7-20200913'\'''
Thread model: single
Supported LTO compression algorithms: zlib
gcc version 11.0.0 20200813 (experimental) ('corev-openhw-gcc-centos7-20200913')
compilation flags include:
-Os -Wa,-march=rv32ic -Wall -Wdouble-promotion -Wextra -Wformat=2 -fdata-sections -ffunction-sections -fno-builtin -fno-builtin-printf -fno-merge-all-constants -g0 -march=rv32ic -s -std=gnu11

What could explain that ecall triggers an exception?
I am a bit confused by this question. ECALL is documented to trigger an exception, indeed that is the purpose of that operation, akin to SYSENTER / SYSCALL on x86/x64.
The idea here is to facilitate a context switch. Functions like div() can be resolved in unpriviledged mode, others like time() cannot (for example, because unpriviledged mode does not allow access to the system clock). So their implementation sets certain registers in a certain way ("please give me the clock's status"), and then triggers an exception (ECALL). The exception handler -- which runs at a higher priviledge level -- checks the value of those registers, which tell it which functionality was required by the caller. The functionality is performed, results are stored in registers, and control is returned to the (unpriviledged) caller.
Why the ecall triggers the default_exception_handler_c and not the ecall_insn_handler? bad hw wiring?
I very much doubt that, because it is elementary functionality. It is much more likely that your exception handling is incorrectly implemented.

Related

Reading a value from a register( which is declared as internal signal)in my design and displaying it transcript window

Is there any way to read a value from a register which is an internal signal in my module and displaying it in the modelsim transcript window using a Tcl script?
I am looking for a proper command for use solving the above problem.
From the Manual pages of Modelsim v10.3a you can find the following command for displaying signal values:
examine
... It examines one or more objects and displays current values (or the values at a specified previous time) in the Transcript window.
The following objects can be examined:
VHDL — signals, shared variables, process variables, constants, generics, and FILE objects
Verilog — nets, registers, parameters, and variables.
To display a previous value, specify the desired time using the -time option.
Note that this command requires the full path to your register (see example below).
For future reference, if you desire to display memory values take a look at mem save and mem display commands.
Example
Suppose you have the following description snippet:
entity core is
port ( ... );
end core;
architecture behav of core is
signal regA : std_logic;
begin
....
-- here your regA signal is assigned some values
end behav;
which is instantiated in your testbench as
entity tb
end
architecture behav of tb is
begin
UUT: entity work.core
port map ( ... );
end behav;
Once you've compiled your files you must run the simulation up to the moment (or past) where you want to display the signal value.
run 30 ns
The command below display regA value at 30 ns:
examine /tb/core/regA
... and this recover its value at 10 ns:
examine -time 10 ns /tb/core/regA

How to force gfortran to stop at First NaN?

My Configuration: Cygwin64, Win7 64 bit, gfortran 4.8.3
I did go through all the Q/A pairs I managed to find, this one is the closest to my problem
Force gfortran to stop program at first NaN
PROBLEM: The fortran code
real :: init_with_NaN ! -finit-real=nan
res = 10 * init_with_NaN
The code is compiled with the following gfortran flags
COLLECT_GCC_OPTIONS='-funderscoring' '-O0' '-g' '-c' '-fmessage-length=0' '-O0' '-g' '-ffpe-trap=invalid,zero,overflow,underflow,precision,denormal' '-Wall' '-c' '-fmessage-length=0' '-Wpedantic' '-std=f2003' '-fall-intrinsics' '-fbacktrace' '-fimplicit-none' '-Wextra' '-Wformat=1' '-Wconversion' '-Wfatal-errors' '-finit-real=nan' '-Wuninitialized' '-fbounds-check' '-v' '-o' 'fsignal_test.o' '-mtune=generic' '-march=x86-64'
Once the code is run, instead of getting a SIGFPE, res is set to be NaN and execution continues.
This is a sub-problem of a million dollar question:
Does gfortran -ffpe-trap=invalid flag really stops the program once it detects a NaN anywhere in the program ? Especially on Cygwin64 env?
A little research showed that:
1) Acc.to https://gcc.gnu.org/onlinedocs/gfortran/Debugging-Options.html, -ffpe-trap works on MOST systems, not all :(
2) Acc. to Division by zero does not throw SIGFPE
"You don't get a signal because the default behavior on most machines
is to pollute your data with NaNs (not-a-number) and infinities. You
have to enable floating point exceptions, and how you do that is
machine specific. Look at the system header fenv.h, if you have one.
The function fesettrapenable enables catching floating point
exceptions on many machines.
Unfortunately, there is no standard function to turn floating point
exceptions handling on"
3) I have checked my cygwin env, fenv.h exists in multiple places but there is no fesettrapenable function anywhere under any *.h file under cygwin64.
4) I do get SIGFPEs: like sqrt(-1), div by zero, overflow, underflow, precision
Here is the full Fortran test project in Eclipse, use it at your hearts content to learn about exceptions on your own platform:
https://drive.google.com/file/d/0B9U1dlb_UCPqU194XzhDNTNkUUU/view?usp=sharing

Splint doesn't know that library function is freeing memory

When using MySQL in C you free the memory using the MySQL API, like so:
MYSQL* connection = NULL;
connection = mysql_init(NULL);
// Stuff...
mysql_close(connection);
But Splint doesn't know that mysql_close is in fact freeing memory, so I get this error:
Fresh storage connection not released before return
A memory leak has been detected. Storage allocated locally is
not released before the last reference to it is lost. (Use
-mustfreefresh to inhibit warning)
How do I tell Splint that mysql_close is deallocating memory? A special annotation to the mysql.h file?
EDIT: OK, maybe the releases *p annotation, if that can be used in a header file. Will try.
EDIT 2: Added /*#releases *sock#*/ to mysql.h, but now get this error:
Releases clauses includes *sock of non-dynamically allocated
type MYSQL
A declaration uses an invalid annotation. (Use -annotationerror to inhibit
warning)
This is the signaure of mysql_close:
void STDCALL mysql_close(/*#notnull#*/ MYSQL *sock) /*#releases *sock#*/;
I believe that proper annotation would be:
void STDCALL mysql_close(/*#special#*/ /*#notnull#*/ MYSQL *sock)
/*#releases sock#*/;
The key, that you have missed is /*#special#*/ annotation, that is required to "activate" so called state clauses. From Splint's documentation, 7.4 State Clauses:
The /*#special#*/ annotation is used to mark a parameter, global
variable, or return value that is described using state clauses.

Catch "Tcl Interpreter Error"

Is there any way to catch the global "Tcl Interpreter Error"? For example I would like to automatically store in some file the message that follows.
The core command for trapping any kind of error thrown by Tcl is catch. It takes at least one argument, a script to evaluate, and returns the result code from evaluating that script. The result code is 1 when an error occurs, 0 when there was no error, and a bunch of other things in other cases (indicating other types of usually-non-error exception). The catch also takes an optional argument that names a variable into which to write the result of evaluating the script or the error message. The global variable errorInfo will contain the stack trace in the case of an error (or from 8.5 onwards you can get the interpreter state dictionary with a further variable name passed to catch).
To trap an error in some script “foo.tcl”, you would use code like this:
if {[catch {source foo.tcl} msg]} {
puts "I got an error: $msg"
puts "The stack trace was this:\n$errorInfo"
}
It's up to you to work out how to write that out to a file if you want. (I use this technique with an outer script that implements a carefully tested error trap and which loads an inner script that does the real work. I find it works well. Or you can call procedures in that “caught” script. Up to you really; Tcl should make all errors trappable, and there are very few conditions which slip through.)
The other route that errors can be reported is via bgerror, which is called to handle errors that occur during event processing. It's a procedure you can write your own version of; it will be given a single argument when called that is the error message, and will have the global errorInfo set correctly when called:
proc bgerror {msg} {
global errorInfo
puts "I got an error in an event: $msg"
puts "The stack trace was this:\n$errorInfo"
}
If there is no implementation of bgerror defined, the stack trace is just written to the stderr channel. If you're using the Tk package, an implementation of bgerror is provided which pops up a dialog box describing the problem.
Try the bgerror or interp bgerror commands.
Read the bgerror documentation, it has a simple example.

microchip exception handling

While running my program on a microchip ICD3 device, the exception handling looks weird. The program will stop response while exception occurs. While checking the code, I noticed that the default-general-exception-handler.c will create an infinite loop. It is really confusing because I cannot know where the error occurs and what is the reason. Does that mean Microchip doesn't support exception handling? Or is there a way to read the error message?
infinite loop:
--- \home\c11067\work\C32\builds\pic32-microchip-release-1.12-20101221-rc2-20101221\pic32-libs\libc\stubs\default-general-exception-handler.c
9D00DD28 1000FFFF beq zero,zero,0x9d00dd28
9D00DD2C 00000000 nop
By defining a _general_exception_handler, it works!
// declared static in case exception condition would prevent
// auto variable being created
static enum {
EXCEP_IRQ = 0, // interrupt
EXCEP_AdEL = 4, // address error exception (load or ifetch)
EXCEP_AdES, // address error exception (store)
EXCEP_IBE, // bus error (ifetch)
EXCEP_DBE, // bus error (load/store)
EXCEP_Sys, // syscall
EXCEP_Bp, // breakpoint
EXCEP_RI, // reserved instruction
EXCEP_CpU, // coprocessor unusable
EXCEP_Overflow, // arithmetic overflow
EXCEP_Trap, // trap (possible divide by zero)
EXCEP_IS1 = 16, // implementation specfic 1
EXCEP_CEU, // CorExtend Unuseable
EXCEP_C2E // coprocessor 2
} _excep_code;
static unsigned int _epc_code;
static unsigned int _excep_addr;
// this function overrides the normal _weak_ generic handler
void _general_exception_handler(void)
{
asm volatile("mfc0 %0,$13" : "=r" (_excep_code));
asm volatile("mfc0 %0,$14" : "=r" (_excep_addr));
_excep_code = (_excep_code & 0x0000007C) >> 2;
while (1) {
// Examine _excep_code to identify the type of exception
// Examine _excep_addr to find the address that caused the exception
}
}
On most microcontrollers, there isn't any code beyond what you put there. In most cases, if an exception occurs and you haven't defined a handler for it, the processor would have no idea how to put up a "Sorry, a system error occurred" dialog box. Using two bytes for a "branch-to-self" instruction is enough to yield a predictable response to an exception; without particular knowledge of any better course of action, a branch-to-self or forced reset is probably as good a response as anything.
PS--Some compilers for various platforms will omit vectors for unused interrupts or exceptions; if such exceptions occur unexpectedly, weird and bizarre things can happen. Some compilers will produce code that will force an immediate reset (note that if watchdog timer is enabled, a jump-to-self will cause a reset, eventually). Some compilers generate an immediate return-from-interrupt (which on some CPU's may be useless, and on others can cause bad behavior). My favorite pattern would be to have all unused interrupts make a call (not a branch) to an UnexpectedInterrupt label, which in the absence of any explicit definition will point to a branch-to-self instruction. If one does that, an UnexpectedInterrupt handler can pop the stack and record what type of unexpected interrupt occurred. I've not seen such a pattern, though, outside my own manually-generated interrupt vector tables.
Just as a heads-up for further PIC32 exception debugging, the exception codes and all the bits in the 'CAUSE' register (the value you're reading into your _excep_code variable before and-ing all the other bits away) are defined in:
PIC32 Family Reference Manual, Section 2.12.9 CAUSE Register
http://ww1.microchip.com/downloads/en/DeviceDoc/61113C.pdf