SystemVerilog LRM has some examples that show how to pass structs in SystemVerilog to\from C through DPI-C layer. However when I try my own example it seems to not work at all in Incisive or Vivado simulator (it does work in ModelSim). I wanted to know if I am doing something wrong, or if it is an issue with the Simulators. My example is as follow:
#include <stdio.h>
typedef struct {
char f1;
int f2;
} s1;
void SimpleFcn(const s1 * in,s1 * out){
printf("In the C function the struct in has f1: %d\n",in->f1);
printf("In the C function the struct in has f2: %d\n",in->f2);
out->f1=!(in->f1);
out->f2=in->f2+1;
}
I compile the above code into a shared library:
gcc -c -fPIC -Wall -ansi -pedantic -Wno-long-long -fwrapv -O0 dpi_top.c -o dpi_top.o
gcc -shared -lm dpi_top.o -o dpi_top.so
And the SystemVerilog code:
`timescale 1ns / 1ns
typedef struct {
bit f1;
int f2;
} s1;
import "DPI-C" function void SimpleFcn(input s1 in,output s1 out);
module top();
s1 in,out;
initial
begin
in.f1=1'b0;
in.f2 = 400;
$display("The input struct in SV has f1: %h and f2:%d",in.f1,in.f2);
SimpleFcn(in,out);
$display("The output struct in SV has f1: %h and f2:%d",out.f1,out.f2);
end
endmodule
In Incisive I run it using irun:
irun -sv_lib ./dpi_top.so -sv ./top.sv
But it SegV's.
In Vivado I run it using
xvlog -sv ./top.sv
xelab top -sv_root ./ -sv_lib dpi_top.so -R
It runs fine until it exits simulation, then there is a memory corruption:
Vivado Simulator 2017.4
Time resolution is 1 ns
run -all
The input struct in SV has f1: 0 and f2: 400
In the C function the struct in has f1: 0
In the C function the struct in has f2: 400
The output struct in SV has f1: 1 and f2: 401
exit
*** Error in `xsim.dir/work.top/xsimk': double free or corruption (!prev): 0x00000000009da2c0 ***
You were lucky that this worked in Modelsim. Your SystemVerilog prototype does not match your C prototype. You have f1 as a byte in C and bit in SystemVerilog.
Modelsim/Questa has a -dpiheader switch that produces a C header file that you can #include into your dpi_top.c file. That way you get a compiler error when the prototypes don't match instead of an unpredictable run-time error. This is the C prototype for your SV code.
typedef struct {
svBit f1;
int f2;
} s1;
void SimpleFcn(
const s1* in,
s1* out);
But I would recommend sticking with C compatible types in SystemVerilog.
Related
This is the relevant part of XS, which should convert an Perl string from UTF-8 to codepoints (unsigned 32-bit integers):
UV *
text2UV (SV *sv, STRLEN *lenp)
{
STRLEN len;
// char *str = SvPV(foo_sv, strlen);
// char *s = SvPV (sv, len); // This original version warns
U8 *s = (U8 *)SvPV (sv, len); // This casts without warning
UV *r = (UV *)SvPVX (sv_2mortal (NEWSV (0, (len + 1) * sizeof (UV))));
UV *p = r;
if (SvUTF8 (sv))
{
STRLEN clen;
while (len)
{
// UV utf8_to_uvchr_buf(const U8 *s, const U8 *send, STRLEN *retlen)
*p++ = utf8n_to_uvchr (s, len, &clen, 0);
if (clen < 0)
croak ("illegal unicode character in string");
s += clen;
len -= clen;
}
}
else
while (len--)
*p++ = *(unsigned char *)s++;
*lenp = p - r;
return r;
}
It throws this warning:
~/github/perl/Text-Levenshtein-BVXS$ make
cp BVXS.pm blib/lib/Text/Levenshtein/BVXS.pm
Running Mkbootstrap for BVXS ()
chmod 644 "BVXS.bs"
"/Users/helmut/perl5/perlbrew/perls/perl-5.32.0/bin/perl" -MExtUtils::Command::MM -e 'cp_nonempty' -- BVXS.bs blib/arch/auto/Text/Levenshtein/BVXS/BVXS.bs 644
"/Users/helmut/perl5/perlbrew/perls/perl-5.32.0/bin/perl" "/Users/helmut/perl5/perlbrew/perls/perl-5.32.0/lib/5.32.0/ExtUtils/xsubpp" -typemap '/Users/helmut/perl5/perlbrew/perls/perl-5.32.0/lib/5.32.0/ExtUtils/typemap' BVXS.xs > BVXS.xsc
mv BVXS.xsc BVXS.c
cc -c -I. -fno-common -DPERL_DARWIN -mmacosx-version-min=10.14 -fno-strict-aliasing -pipe -fstack-protector-strong -I/usr/local/include -I/opt/local/include -DPERL_USE_SAFE_PUTENV -O3 -DVERSION=\"0.01\" -DXS_VERSION=\"0.01\" "-I/Users/helmut/perl5/perlbrew/perls/perl-5.32.0/lib/5.32.0/darwin-2level/CORE" BVXS.c
BVXS.xs:26:35: warning: passing 'char *' to parameter of type 'const U8 *' (aka 'const unsigned char *') converts between pointers to integer types with different sign [-Wpointer-sign]
*p++ = utf8n_to_uvchr (s, len, &clen, 0);
^
/Users/helmut/perl5/perlbrew/perls/perl-5.32.0/lib/5.32.0/darwin-2level/CORE/utf8.h:74:54: note: expanded from macro 'utf8n_to_uvchr'
utf8n_to_uvchr_error(s, len, lenp, flags, 0)
^
/Users/helmut/perl5/perlbrew/perls/perl-5.32.0/lib/5.32.0/darwin-2level/CORE/utf8.h:76:45: note: expanded from macro 'utf8n_to_uvchr_error'
utf8n_to_uvchr_msgs(s, len, lenp, flags, errors, 0)
^
/Users/helmut/perl5/perlbrew/perls/perl-5.32.0/lib/5.32.0/darwin-2level/CORE/inline.h:1781:36: note: passing argument to parameter 's' here
Perl_utf8n_to_uvchr_msgs(const U8 *s,
^
1 warning generated.
rm -f blib/arch/auto/Text/Levenshtein/BVXS/BVXS.bundle
cc -mmacosx-version-min=10.14 -bundle -undefined dynamic_lookup -L/usr/local/lib -L/opt/local/lib -fstack-protector-strong BVXS.o -o blib/arch/auto/Text/Levenshtein/BVXS/BVXS.bundle \
\
It works and passes my tests. But if I want to deliver it to CPAN the distribution should not throw warnings.
Decode it with own code in C would be a work-around (and faster).
For me it looks like a bug in the XS macros and/or the example in the documentation are wrong.
The interplay of U8 and char in the API is a bit weird. You might ask #p5p to see why it works that way.
Failing that, though, would some plain typecasting suppress the warnings? Is this in a public repository somewhere?
Aside: SvPV is evil. Its prevalence in XS modules causes quite a lot of pain. Avoid it when possible. See: https://dev.to/fgasper/perl-s-svpv-menace-5515
Update: This looks to be a case where it’s necessary to break the abstraction. Alas.
In Windbg I have a script that iterates through the frames of a stack and does a good job of pulling back things of interest, echoing them to the Command Window (it just sniffs things out that could require further investigation).
In certain frames, there will be a this that I'm interested in some details of. I can certainly extract the details fine, but I'd like to get the actual class type from it too. I know that if I then do a dv /t I will see something like the following:
0:115> .frame 14
0:115> dv /t
class foo1 * this = 0x00000000e9ed0010
I would like a way of being able to pass just foo1 to a .printf command.
In frames that have more than simply this, I can restrict output by using the pattern dv /t this obviously, but is there a good way of having something like what follows in a frame and me being able to extract just foo1?
0:115> .frame 17
0:115> dv /t
class foo1 * this = 0x00000000f3e2f568
class foo2 * bar2 = 0x0000000000000001
bool _somebool = true
Doing what follows is very close to the limited output I'd like... but I just want to neaten it up.
0:115> .frame 17
0:115> dv /t this
class foo1 * this = 0x00000000f3e2f568
Following the example code from blabb:
0:000> dv /t
class Time * this = 0x001efb24
int h = 0n23
int m = 0n59
int s = 0n59
0:000> dv /t this
class Time * this = 0x001efb24
0:000> some command
Time
The third command is what I'm looking for.
What I understood is: you need a command that takes foo1 as a parameter and gives an output like dv /t but just for all foo1.
IMHO, it's hardly possible with builtin WinDbg functionality. You could fiddle around with .foreach inculding $spat and the like.
One possibility is .shell along with the command line tool findstr or Cygwin grep. But that's not convenient, because it always outputs Process started etc. You could again work around this using .foreach and skipping some tokens, but that's tedious.
There are grep implementations for WinDbg such as long123king's grep plugin and if I recall correctly, there's also a grep implementation in PDE.
Then there is pykd, which has the powers of Python and let's you do basically anything.
i am not sure i understand what you need
but have you given the new dx expression evaluator a try
for example
0:000> dv /t
class Time * this = 0x001efb24
int h = 0n23
int m = 0n59
int s = 0n59
0:000> dv /t this
class Time * this = 0x001efb24
0:000> dx #$curstack.Frames[0].LocalVariables
#$curstack.Frames[0].LocalVariables
this : 0x1efb24 [Type: Time *]
0:000> dx #$curstack.Frames[0].LocalVariables.this
#$curstack.Frames[0].LocalVariables.this : 0x1efb24 [Type: Time *]
[+0x000] hour : 23 [Type: int]
[+0x004] minute : 59 [Type: int]
[+0x008] second : 59 [Type: int]
you can enhance this with javascript to fine tune it to you needs
here is how you can enhance this with javascript
make a file whateverfoo.js with contents below
function log(logstr) {
return host.diagnostics.debugLog(logstr + "\n")
}
function locvartgttyp(frameno)
{
log( host.currentThread.Stack.Frames[frameno].LocalVariables.this.targetType.name)
}
and use it like
:\>echo %wdbg%
"c:\Program Files\Windows Kits\10\Debuggers\x86\cdb.exe"
:\>%wdbg% time.exe
Microsoft (R) Windows Debugger Version 10.0.17763.132 X86
0:000> g time!main
time!main:
01237a80 55 push ebp
0:000> tc;t
time!Time::Time:
01231140 55 push ebp
0:000> dv /t
class Time * this = 0x00000002
int h = 0n23
int m = 0n59
int s = 0n59
0:000> .load jsprovider
0:000> .scriptload c:\wdscr\locvar.js
JavaScript script successfully loaded from 'c:\wdscr\locvar.js'
0:000> dx #$scriptContents.locvartgttyp(0)
Time *
#$scriptContents.locvartgttyp(0)
0:000>
I'm trying to manipulate guid from C++. Whenever I attempt to serialize a guid, I get a null pointer.
U g={0};
auto k = ku(g);
auto p = ::b9(2, k);
First two lines are straight from the manual for creating a null guid. This will result in p == 0.
Really what I was attempting to do was creating a list of guid and then serializing:
k = ktn(UU, 3)
kU(k)[0] = <an instance of U with the g bytes initialized>
kU(k)[1] = <an instance of U with the g bytes initialized>
kU(k)[2] = <an instance of U with the g bytes initialized>
That did not work when attempting to serialize.
I believe you should be using 3 as the first argument to b9. For example:
jmcmurray#homer ~/c $ more test.c
#include"k.h"
K f(K x)
{
K k = ktn(UU,3);I j=0;
for(j=0;j<3;j++){
U g={0};I i=0;
for(i=j;i<j+16;i++){
g.g[i] = (unsigned char)i;
}
kU(k)[0] = g;
}
return b9(3,k);
}
jmcmurray#homer ~/c $ gcc -shared -fPIC -DKXVER=3 test.c -o test.so
jmcmurray#homer ~/c $ q
KDB+ 3.5 2017.11.30 Copyright (C) 1993-2017 Kx Systems
l64/ 8()core 16048MB jmcmurray homer.aquaq.co.uk 192.168.1.57 EXPIRE 2019.06.30 AquaQ #52428
q)f:`:./test 2:(`f;1)
q)f[]
0x010000003e000000020003000000000002030405060708090a0b0c0d0e0f00ae67af727f000..
q)-9!f[]
00000203-0405-0607-0809-0a0b0c0d0e0f 001868af-727f-0000-6062-67af727f0000 a0a..
q)
Here I am able to return a serialised list of GUIDs from my shared object & deserialize on the q side. When I tried with 2 as in your example I got a 'type error when running the function in q.
According to https://code.kx.com/q/interfaces/capiref/#b9-serialize 3 means
unenumerate, compress, allow serialization of timespan and timestamp
2 is the same without "compress". So I guess you must compress GUIDs?
I am writing this F90 program to compute a function in fortran which takes the input from a .mat file and save the results in another .mat file.
I followed this answer to get the code compiled and correctly linked. This is my makefile command:
gfortran -g -fcheck=all binhkorn_mat.F90 -I/usr/local/MATLAB/R2015b/extern/include/ -L/usr/local/MATLAB/R2015b/bin/glnxa64 -cpp -o binhkorn_mat -lmat -lmx -Wl,-rpath /usr/local/MATLAB/R2015b/bin/glnxa64/
The output file is apparently correctly compiled, but then once I run the program the following SF appears (I'm working on LINUX Ubuntu 14.04 LTS):
Program received signal SIGSEGV: Segmentation fault - invalid memory reference.
Backtrace for this error:
#0 0x7FD650063F27
#1 0x7FD6500644F4
#2 0x7FD64FCBCD3F
#3 0x7FD64FDD7AF6
#4 0x400A3F in binhkorn_mat at binhkorn_mat.F90:17 (discriminator 2)
./binhkorn_mat: Segmentation fault
I can't figure out if there's an error with the compiler or if I did something wrong with the pointers/functions definitions. Here's the code (binhkorn_mat.F90):
#include "fintrf.h"
PROGRAM binhkorn_mat
IMPLICIT NONE
mwPointer matOpen, matGetVariable, matPutVariable
mwPointer mpin, mpX, mpout, mpcf
INTEGER :: i,j
REAL*8, DIMENSION(2) :: x
REAL*8, DIMENSION(4) :: cf
!input/output through .mat f
mpin = matOpen('X.mat', 'u')
mpX = matGetVariable(mpin, 'X')
CALL mxCopyPtrToReal8(mpX, x, 2)
CALL matClose(mpin)
!fitness functions
cf(1) = ((x(1)-2)**2 + (x(2)-1)**2 + 2)
cf(2) = (9*x(1) + (x(2)-1)**2)
!constraints
cf(3) = x(1)*x(1) + x(2)*x(2) - 225
cf(4) = x(1) - 3*x(2) + 10
!output file created
CALL mxCopyReal8ToPtr(cf, mpcf, 4)
mpout = matOpen('cf.mat', 'w')
mpcf = matPutVariable(mpout, 'cf', mpcf)
CALL matClose(mpout)
END PROGRAM
The X.mat file is correctly created by an external Matlab script and contains a variable named X which is a 2-element row vector.
I basically misunderstood how to use of many functions. The pointers i supplied as input to some of them were not the correct ones. I post here the working solution:
#include "fintrf.h"
PROGRAM binhkorn_mat
IMPLICIT NONE
mwPointer matOpen, matGetVariable!, matPutVariable
mwPointer mxGetData, mxGetNumberOfElements, mxCreateNumericArray
mwPointer mpin, mpX, mpout, mpcf
mwSize ndim
mwSize dims(2)
INTEGER :: s
INTEGER*4 mxClassIDFromClassName
CHARACTER (LEN = 6) :: classname
REAL*8, DIMENSION(2) :: x
REAL*8, DIMENSION(4) :: cf
!input/output through .mat f
mpin = matOpen('X.mat', 'r')
mpX = matGetVariable(mpin, 'X')
CALL mxCopyPtrToReal8(mxGetData(mpX), x, mxGetNumberOfElements(mpX))
!CALL matClose(mpin)
!fitness functions
cf(1) = ((x(1)-2)**2 + (x(2)-1)**2 + 2)
cf(2) = (9*x(1) + (x(2)-1)**2)
!constraints
cf(3) = x(1)*x(1) + x(2)*x(2) - 225
cf(4) = x(1) - 3*x(2) + 10
!output .mat file created and filled
s = size(cf)
ndim = 2
classname = 'double'
dims(1) = 1
dims(2) = s
mpcf = mxCreateNumericArray(ndim, dims, mxClassIDFromClassName(classname), 0)
CALL mxCopyReal8ToPtr(cf, mxGetData(mpcf), mxGetNumberOfElements(mpcf))
mpout = matOpen('cf.mat', 'w')
CALL matPutVariable(mpout, 'cf', mpcf)
!CALL matClose(mpout)
END PROGRAM
I am trying to use unicode variable names in g++.
It does not appear to work.
Does g++ not support unicode variable names, ... or is there some subset of unicode (from which I'm not testing in).
Thanks!
You have to specify the -fextended-identifiers flag when compiling, you also have to use \uXXXX or \uXXXXXXXX for unicode(atleast in gcc it's unicode)
Identifiers (variable/class names etc) in g++ can't be of utf-8/utf-16 or whatever encoding,
they have to be:
identifier:
nondigit
identifier nondigit
identifier digit
a nondigit is
nondigit: one of
universalcharactername
_ a b c d e f g h i j k l m n o p q r s t u v w x y z
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
and a universalcharactername is
universalcharactername:
\UXXXXXXXX
\uXXXX
Thus, if you save your source file as UTF-8, you cannot have a variable like e.g.:
int høyde = 10;
it had to be written like:
int h\u00F8yde = 10;
(which imo would beat the whole purpose - so just stick with a-z)
A one-line patch to the cpp preprocessor allows UTF-8 input. Details for gcc are given at
https://www.raspberrypi.org/forums/viewtopic.php?p=802657
however, since the preprocessor is shared, the same patch should work for g++ as well. In particular, the patch needed, as of gcc-5.2 is
diff -cNr gcc-5.2.0/libcpp/charset.c gcc-5.2.0-ejo/libcpp/charset.c
*** gcc-5.2.0/libcpp/charset.c Mon Jan 5 04:33:28 2015
--- gcc-5.2.0-ejo/libcpp/charset.c Wed Aug 12 14:34:23 2015
***************
*** 1711,1717 ****
struct _cpp_strbuf to;
unsigned char *buffer;
! input_cset = init_iconv_desc (pfile, SOURCE_CHARSET, input_charset);
if (input_cset.func == convert_no_conversion)
{
to.text = input;
--- 1711,1717 ----
struct _cpp_strbuf to;
unsigned char *buffer;
! input_cset = init_iconv_desc (pfile, "C99", input_charset);
if (input_cset.func == convert_no_conversion)
{
to.text = input;
Note that for the above patch to work, a recent version of iconv needs to be installed that supports C99 conversions. Type iconv --list to verify this, otherwise, you can install a new version of iconv along with gcc as described in the link above. Change the configure command to
$ ../gcc-5.2.0/configure -v --disable-multilib \
--with-libiconv-prefix=/usr/local/gcc-5.2 \
--prefix=/usr/local/gcc-5.2 \
--enable-languages="c,c++"
if you are building for x86 and want to include the c++ compiler as well.