C: declaring multipe pointer variables in same declaration statement

First thing first, never declare multiple pointer variables in same declaration statement. Don’t mix declaration of pointer and non-pointer variables in same line. Following this will save you a lot of debugging time in the future.

But in case, you are forced do it or you are debugging code written by somebody else, this short post can help you.

What does this code really mean?

int* c, d;

It is clear that c is a pointer to integer. But what about d? Is it integer or pointer to integer? Ofcourse, it is integer not a pointer to integer. Using declaration as above is very ambigious. Avoid it any cost. Instead, declare them on their own statements.

int* c;
int d;

Much clear. Isn’t it?

It is also better to follow this rule when all variables are pointers. Also, I prefer to put the star next to varaible name instead of the variable type.

int *p, *q;

is more intuitive than

int* p, *q;

C++: Initializing parent class member variables in derived class constructor

Usually we initialize member variables in constructor using initialization list.

class Base {
public:
    int i;
    explicit Base(int _i) : i(_i) {
        //other initialization code
    }
};

But we cannot initialize the parent class public or protected member variable in derived class constructor’s initialization list.

class Derived: public Base {
public:
  int j;
  Derived(int _i, int _j) : i(_i), j(_j) {

  }
};

The above code will produce the following error:

par_var_init.cpp: In constructor ‘Derived::Derived(int, int)’:
par_var_init.cpp:16:28: error: class ‘Derived’ does not have any field named ‘i’
Derived(int _i, int _j) : i(_i), j(_j) {

Using parent constructor

The correct way to do this is by calling the base class constructor to initialize its variables.

class Derived: public Base {
public:
  int j;
  Derived(int _i, int _j) : Base(i), j(_j) {

  }
};

Initializing parent’s member variables in derived class constructor’s body

It is possible to initialize parent’s member variables in derived constructor’s body.

class Derived: public Base {
public:
  int j;
  Derived(int _i, int _j) : j(_j) {
    i = _i;
  }
};

Note: the following approach is wrong!

class Derived: public Base {
public:
  int i;
  int j;
  Derived(int _i, int _j) : i(_i), j(_j) {
  }
};

This will create a new variable in derived class called i that is separate from Base::i.

C++11 regex using g++

Boost regex has been accepted into C++11. So, I decided to give it a try using g++.

#include<iostream>
#include<string>
#include<regex>

using namespace std;

int main() {
        string str("2 a\n3 b\n4 c\n5 d\n6 c");
        regex r("[0-9]");

        regex_iterator<string::iterator> start(str.begin(), str.end(), r);
        regex_iterator<string::iterator> end;

        while(start != end) {
                cout << start->str() << endl;
                ++start;
        }
}

I was surprised to get a big fat link-time error:

/tmp/cc80j8Z8.o: In function `main':
regex1.cpp:(.text+0x133): undefined reference to `std::regex_iterator<__gnu_cxx::__normal_iterator<char*, std::string>, char, std::regex_traits >::regex_iterator(__gnu_cxx::__normal_iterator<char*, std::string>, __gnu_cxx::__normal_iterator<char*, std::string>, std::basic_regex<char, std::regex_traits > const&, std::bitset)’
regex1.cpp:(.text+0x13f): undefined reference to `std::regex_iterator<__gnu_cxx::__normal_iterator<char*, std::string>, char, std::regex_traits >::regex_iterator()’
regex1.cpp:(.text+0x150): undefined reference to `std::regex_iterator<__gnu_cxx::__normal_iterator<char*, std::string>, char, std::regex_traits >::operator->()’
regex1.cpp:(.text+0x1a9): undefined reference to `std::regex_iterator<__gnu_cxx::__normal_iterator<char*, std::string>, char, std::regex_traits >::operator++()’
regex1.cpp:(.text+0x1bf): undefined reference to `std::regex_iterator<__gnu_cxx::__normal_iterator<char*, std::string>, char, std::regex_traits >::operator!=(std::regex_iterator<__gnu_cxx::__normal_iterator<char*, std::string>, char, std::regex_traits > const&)’
collect2: error: ld returned 1 exit status

Seems like gcc 4.8.2, delivered by my distribution doesn’t support regex yet. So, we are forced to use Boost regex for now. Or use g++ 4.9.0 instead, which has regex implemented. To install the latest g++ release, execute the following command in the terminal:

sudo add-apt-repository ppa:ubuntu-toolchain-r/test
sudo apt-get update
sudo apt-get install g++-4.9

To compile the code with g++4.9:

g++-4.9 --std=c++11 regex1.cpp -o regex1

C++: vector of arrays

In C++ arrays cannot be stored in vectors. This restriction is due to the fact that arrays cannot be copy constructed or assigned. For example, this won’t compile in c++

To work around this limitation, c++11 has introduced a new container called std::array. std::array is just a template class that encapsulates a static array. It cannot be resized and its size should be know at compile time. Here is a small example on how to create a vector of arrays.

Passing and receiving different SystemVerilog datatypes with C/C++ using DPI

SystemVerilog makes interaction with C/C++ a piece of cake. Now, you can directly call C/C++ functions as functions or tasks in SystemVerilog(aka. Importing) and call SystemVerilog functions or tasks from C/C++(aka. Exporting). In this article, we will see how we can pass and receive different SystemVerilog datatypes through DPI.

Return type of imported C/C++ functions

First thing to note is that imported functions can only return single bit types and 2-state int or double types that are not vectors.

This rule rules out all 4-state types except single bit types

  • logic packed arrays, logic unpacked arrays
  • wire, wire packed arrays, wire unpacked arrays
  • reg, reg packed arrays, reg unpacked arrays

and all vector types

  • bit packed arrays, bit unpacked arrays
  • logic packed arrays, logic unpacked arrays
  • wire packed arrays, wire unpacked arrays
  • reg packed arrays, reg unpacked arrays

So what we are left with are fixed width int and double types:

  • bit
  • byte
  • shortint
  • int
  • shortreal
  • real
  • logic

You can pass these types as arguments and receive these types as return from an imported functions. Here is an example of passing and receiving single bit bit and logic.

import "DPI-C" context function bit and_bit(input bit a, b);
import "DPI-C" context function logic and_logic(input logic a, b);
svBit
and_bit(
    svBit a,
    svBit b) {
	return a && b;
}

svLogic
and_logic(
    svLogic a,
    svLogic b) {
	return a && b;
}

You should have noticed two new types on C/C++ side: svBit and svLogic. These are usually 8 bit unsigned char types but only the lsb bit is used.

Passing and receiving packed arrays

Passing and receiving packed arrays is easier than dealing with unpacked arrays. On C side, packed bit vectors are called svBitVecVal and packed logic vectors are called svLogicVecVal. Bit vectors are plain int types. If the vector size exceeds the size that can be stored inside an integer, the bit vectors are passed as array of svBitVecVal.
Logic vectors are little bit more complicated because they represent 4-state values. svLogicVecVal is a structure with two members aval and bval. aval stores the plain bit representation of logic vector while bval stores whether the corresponding bit is ‘0’, ‘1’ or ‘x’, ‘z’. If the vector size exceeds the size that can be stored inside an integer, the logic vectors are passed as array of svLogicVecVal.

[ada]
import “DPI-C” context function void add_bpv(input bit [3:0] a, b, output bit [3:0] c);
import “DPI-C” context function void add_lpv(input logic [3:0] a, b, output logic [3:0] c);
[/ada]

void
add_bpv(
    const svBitVecVal* a,
    const svBitVecVal* b,
    svBitVecVal* c) {
	*c = *a + *b;
}

void
add_lpv(
    const svLogicVecVal* a,
    const svLogicVecVal* b,
    svLogicVecVal* c) {
	c->aval = a->aval + b->aval;
	c->bval = 0;
}

As you can see, we are using output arguments to receive vector types because imported functions cannot return vector types.

Passing and receiving unpacked vectors

Unpacked arrays are sent as arrays of svBit or scLogic to C. There is no way to directly access the integer represented by putting all the individual bits together without calculating it.

import "DPI-C" context function void and_buv(input bit a[3:0], b [3:0], output bit c [3:0]);
import "DPI-C" context function void or_luv(input logic a[3:0], b [3:0], output logic c [3:0]);
void
and_buv(
    const svBit* a,
    const svBit* b,
    svBit* c) {
	for(int i = 0; i < 4; i++) {
		c[i] = a[i] & b[i];
	}
}
void
or_luv(
    const svLogic* a,
    const svLogic* b,
    svLogic* c) {
	for(int i = 0; i < 4; i++) {
		c[i] = a[i] | b[i];
	}
}

Passing and receiving mixed packed and unpacked arrays

As expected, mixed packed and unpacked arrays are represented as arrays of svBitVecVal or svLogicVecVal. If the size of the packed dimension is greater than what can fit inside an integer, mixed packed and unpacked arrays are represented as arrays of arrays of svBitVecVal or svLogicVecVal.

import "DPI-C" context function void add_bpuv(input bit [0:3]a[0:3], b [0:3], output bit [0:3]c [3:0]);
void
add_bpuv(
    const svBitVecVal* a,
    const svBitVecVal* b,
    svBitVecVal* c) {
	for(int i = 0; i < 4; i++) {
		c[i] = a[i] + b[i];
	}
}

Passing and receiving structs

Structs are passed can be passed and received directly. Individual members are representing based on their data type as discussed above.

typedef struct {
shortint mem1;
logic [7:0] mem2;
bit [7:0] mem3;
} struct_t;

import "DPI-C" context function void add_struct(input struct_t a, b, output struct_t c);
void
add_struct(
    const struct_t* a,
    const struct_t* b,
    struct_t* c) {
	c->mem1 = a->mem1 + b->mem1;
	c->mem2[0].aval = a->mem2[0].aval + b->mem2[0].aval;
	c->mem2[0].bval = 0;
	c->mem3[0] = a->mem3[0] + b->mem3[0];
}

Here is the full verilog and c code.


c++: dynamic_cast

dynamic_cast is used to cast a pointer of a polymorphic objects(pointer to base or derived classes) up or down the inheritance hierarchy. It is more safe than reinterpret_cast because it performs a type check at run time. dynamic_cast uses run time information to figure out if the classes are polymorphically related. For this reason, dynamic_cast requires that RTTI is enabled in the compiler. This also means that the pointer being casted should be polymorphic(has virtual functions). If the type of the pointer being casted is not polymorphic, a compile time error is thrown.

Lets consider these three classes(1 base class and two derived classes) for illustration:

To cast a pointer of Base object to a pointer of Derived object:

To cast a pointer of Derived object to a pointer of Base object:

dynamic_cast assures type safety by returning a NULL pointer when the casted pointer cannot be safely converted to destination type. Hence, the returned pointer should be tested for NULL before use.

Note: If you don’t want to have any virtual functions, the best thing to do is to make the destructor virtual.

C++: Copy constructor and assignment constructor

Usually C++ beginners confuse between copy constructor and assignment operator. Though they do almost the same thing, they have their own purposes and understanding it is very important. While copy constructor is a constructor, assignment operator is an operator. This means that copy constructor is used to create new objects from existing objects, while assignment operator is used to assign content of an existing object to another existing object.

We will use the class Assignable defined in the code snippet below for illustration purposes throughout the article.

Copy constructor

Copy constructor is a constructor used by the compiler to create new instances of a class from existing instances.

Copy constructor is usually called(not necessarily because c++ allows compilers to optimize the copy away when it is posible)
1) When an instance of a class is passed as value to a function

2) When a new instance is created by passing a reference to an existing instance

3) When an instance of a class is returned by value from a function

Note: Some compilers are smart enough to identify this situation and avoid copy construction and destruction of temporary object. This optimization is called Return Value Optimization.

Assignment operator

Assignment operator is an operator that is invoked when an instance of a class is assigned to another.

This is the entire code to simulate all these behaviors of copy constructor and assingnment operator.

Golang: Call C code from Go code

Be it a library written in C or parts of your implementation you want to implement in C, it is very easy to call them from Golang.
All C functions, types, convenience function, etc are exported through C package in Golang. The C code can be directly embedded in Go code by writing it as comments directly above the statement that imports C package.

To run the above example execute the following command:

go run cgo1.go

You can also write C code in a separate .c file and access them in Go.


To run the above example execute the following command:

go run cgo2.go

To call a Go function in C code, export the Go function by writing the following snippet directly above the Go function:

//export func-name

All the exported Go functions can be accessed from C by including the auto-generated header file _cgo_export.h.


It should noted that this example won’t work unless you place the project under $GOPATH/src and execute go build on the project. For example move the two files to $GOPATH/src/cgo3 and execute the following commands:

go build cgo3
./cgo3