niedziela, 6 maja 2018

Visual Studio Express 2017 install problems

Visual Studio Express is still interesting as its license is has no "Organizational License" clause (https://www.visualstudio.com/license-terms/mlt080317/ vs https://www.visualstudio.com/license-terms/mlt553321/).
Unfortunately installation (at least for me - Win10 Enterprise) was huge pain.
Here are installation hints:

  1. Download and start installer - perhaps you will see error message: "At most one command parameter can be specified..."
  2. If this is the case then copy extracted installer from temporary folder (use TaskManager to find location) - in my case it was folder with name "vs_bootstrapper_d15"
  3. Start installer (using command line) from copied location - in that case I observed no "At most..." error, but after installation start another error had appeared - unable to download "sqlsysclrtypes"
  4. Solution to "sqlsysclrtypes" problem is to download the whole installer locally (using "vs_setup_bootstrapper.exe --layout C:\vs2017offline --lang en-US") and then start "sqlsysclrtypes.msi" manually.
  5. After system restart (required after "sqlsysclrtypes.msi" installation) VSExpress2017 installation was successful.

wtorek, 1 maja 2018

Jacinto J6Eco (DRA72x) hypervisor startup

Normal way to start hypervisor for ARM (e.g. to start XEN) is to start non-secure mode via enter into monitor mode using SMC instruction. Next from exception handler update NS (and HCE) bit in SCR (Secure Configuration Register) register ("1" for non-secure) and exit monitor exception handler in non-secure mode (PL1 to be able to switch into PL2). Additionally before SMC call monitor exception handler must be registered.
Such code (of course far more complicated e.g. due to multicore support) can be found in U-Boot bootloader (u-boot/arch/arm/cpu/armv7/nonsec_virt.S).
Fortunately for J6Eco DRA72x (and J6Entry - DRA71x) everything is already prepared and simple "SMC #1" call is enough to start hypervisor.
Example code:

.arch_extension sec
.arch_extension virt
.text
.align 2
.global start_hypervisor
.type start_hypervisor, function
start_hypervisor:
    ldr r12, =0x102
    ldr r0, =HYPERVISOR_ADDR
    smc #1

References




niedziela, 4 marca 2018

ARMv7-a vs Cortex-A7 vs Cortex-A8 vs TI DRA62x +VFP +NEON


"Linaro focuses on the use of the ARM instruction set in its versions 7a (32-bit) and 8 (64-bit) including concrete implementations of these, such as SoCs that contain Cortex-A5, Cortex-A7, Cortex-A8, Cortex-A9, Cortex-A15, Cortex-A53 or Cortex-A57 processor(s)."(https://en.wikipedia.org/wiki/Linaro)

"The ARM Cortex-A8 is a 32-bit processor core licensed by ARM Holdings implementing the ARMv7-A architecture." (https://en.wikipedia.org/wiki/ARM_Cortex-A8)

https://en.wikipedia.org/wiki/Comparison_of_ARMv7-A_cores

https://en.wikipedia.org/wiki/ARM_architecture#VFP


"What is VFP?
VFP is a floating point hardware accelerator. It is not a parallel architecture like Neon. Basically it performs one operation on one set of inputs and returns one output. It's purpose is to speed up floating point calculations. If a processor like ARM does not have floating hardware, then it relies on software math libraries which can prohibitively slow down floating point calculations. The VFP supports both single and double precision floating point calculations compliant with IEEE754. Further, the VFP is not fully pipelined like Neon, so it will not have equivalent performance to Neon.
Neon and VFP both support floating point, which should I use?
The VFPv3 is fully compliant with IEEE 754
Neon is not fully compliant with IEEE 754, so it is mainly targeted for multimedia applications
.. example of showing how Neon pipelining will outperform VFP...
Compile the above function for both Neon and VFP and compare results:
arm-none-linux-gnueabi-gcc -O3 -march=armv7-a -mtune=cortex-a8 -mfpu=neon -ftree-vectorize -mfloat-abi=softfp
arm-none-linux-gnueabi-gcc -O3 -march=armv7-a -mtune=cortex-a8 -mfpu=vfp -ftree-vectorize -mfloat-abi=softfp"
(http://processors.wiki.ti.com/index.php/Cortex-A8)

"Using NEON and VFPv3 on Cortex-A8
The compiler supports two different options to control NEON and VFPv3.

--float_support=VFPv3 --neon

The --float_support=VFPv3 option instructs the compiler to generate code that utilizes the VFPv3 coprocessor for both double and single precision floating point operations. The option is also used to enable the assembler to accept VFPv3 instructions in assembly source. To enable VFPv3 the EABI mode must also be enabled through the --abi=eabi option. This is necessary because the calling convention for floating point paramemters changes when VFPv3 is enabled and that convention is only supported in EABI mode.

The --neon option instructs the compiler to automatically vectorize loops to use the NEON instructions. To get benefit from this option you should be using --opt_level=2 or higher and be generating code for performance by using the --opt_for_speed=[3-5] option.
Combining options
The TI ARM compiler supports four modes related to Cortex-A8, NEON, and VFPv3. By default neither NEON or VFPv3 is enabled. In addition to the default the following 3 modes are supported:
VFP enabled without NEON
The compiler will generate VFPv3 instructions for single and double precision floating point operations
NEON enabled without VFP
In this mode the compiler will generate NEON instructions for SIMD integer operations. It will not generate NEON instructions to vectorize floating point operations. The motivation for not allowing floating point NEON instructions if VFP is not enabled is because it is possible to have an integer only variant of NEON implemented. In order for the NEON unit to support floating point operations the VFPv3 coprocessor must be present.
NEON enabled and VFP enabled
In this mode the compiler will generate a mix of NEON and VFP instructions. The NEON instructions can be either integer or floating point.
VFPv3 vs. NEON performance
A common question with regard to TI ARM compiler's support for NEON is how to get more floating point operations on the NEON unit instead of the VFPv3. The reason this is desirable is because the VFPv3 coprocessor is not a pipelined architecture on the Cortex-A8, but the NEON is. The compiler will always use VFP instructions for scalar floating point operations, even if the --neon option is used. The hardware is capable of issuing VFP instructions on the NEON coprocessor if the following conditions are met:

The instruction must be a single precision data processing instruction
The processor must be in flush-to-zero mode. In this mode the processor will treat all denormalized numbers as zero.
The processor must be in default NaN mode. In this mode the operation will return the default NaN regardless of the input, whereas in full-compliance mode the returned NaN follows the rules in the ARM Architecture Reference Manual.
The FPEXC.EX bit must be set to 0. This tells the processor that there is no additional state that must be handled by a context switch."
(http://processors.wiki.ti.com/index.php/Using_NEON_and_VFPv3_on_Cortex-A8)

DRA62x Automotive Application DSP + ARM Processors
The ARM Cortex-A8 processor has a Harvard architecture and provides a complete high-performance subsystem, including:
• ARM Cortex-A8 Integer Core
• Superscalar ARMv7 Instruction Set
• Thumb-2 Instruction Set
• Jazelle RCT Acceleration
• CP14 Debug Coprocessor
• CP15 System Control Coprocessor
• NEON™ 64-/128-bit Hybrid SIMD Engine for Multimedia
• Enhanced VFPv3 Floating-Point Coprocessor
• Enhanced Memory Management Unit (MMU)
• Separate Level-1 Instruction and Data Caches
• Integrated Level-2 Cache
• 128-bit Interconnect with Level 3 Fast (L3) System Memories and Peripherals
• Embedded Trace Module (ETM).

sobota, 12 listopada 2016

base class operator== detection

Scenario:
Class for items storage. Items can be added, read, updated. In case of modification callback notification is sent to all listeners.
To discover modification operator==() can be used. It seems to be natural, non-intrusive solution.
Seems to be fine, but problem comes with inheritance.
Consider types:

struct A {
A(int v) : v(v) {}

int v;

friend bool operator==(const A &lhs, const A &rhs)
{
return lhs.v == rhs.v;
}
};
struct B : A {
B(int v, int w) : A(v), w(w) {}

int w;
};


Note that opeartor==() is defined as friend (therefore not class member - see: ADL, friend name injection, Barton–Nackman trick) but it can also be defined as member function or global function.


The potential problem is visible here:

A a1{1}, a2{1};

std::cout << (a1 == a2); B b1{1,1}, b2{1,2}; std::cout << (b1 == b2);


Both print '1', but is 'b1' really equal to 'b2'?
According to current implementation yes, because only A part of B-type object is compared.
The real problem is no notification of such potential problem. And when generic code is used to compare object, where types are defined in different files it might be easy to forget about operator==() definition for class B.
To avoid potential problem it might be better to decide that such situation is prohibited and shall end in compile-time error.
Required is compile time checking if some type (some, because comparison will be used in generic code) has defined operator==.
Tool to solve the problem might be found e.g. in Boost (has_equal_to from typetraits or Concept Check Library), but simple solution is presented here http://stackoverflow.com/a/6536204/122054.
For C++98:

namespace CHECK
{
class No { bool b[2]; };
template No operator== (const T&, const Arg&);

bool Check (...);
No& Check (const No&);

template
struct EqualExists
{
enum { value = (sizeof(Check(*(T*)(0) == *(Arg*)(0))) != sizeof(No)) };
};
}


Simplified version for C++11:

namespace CHECK
{
struct No {};
template No operator== (const T&, const Arg&);

template
struct EqualExists
{
enum { value = !std::is_same<decltype(*(T*)(0) == *(Arg*)(0)), No>::value };
};
}


Using CHECK::EqualExists::value with static assert allows to detect potential problem.

niedziela, 12 czerwca 2016

Old dog,old tricks (in C++)

Compile time safety, compile time error handling - all about typesystem, constness, ...

C-array safety

If function uses constant length array it is tempting to use:


void f(int t[3])
{
...
t[2] = ...;
}

...

int t[3];
f(t);


as array size is merely for human-programmer, it is possible to use:


int t[4];
f(t);


which perhaps is ok (but not nice).
But it is also possible to do


int t[2];
f(t);


Which for sure is wrong.

Solution to ensure strict array size is:


void f(int (&t)[3])
{
...
}


Now only three elements arrays are allowed.
BTW - above construct is frequently used for C-array handling in templates.

poniedziałek, 7 grudnia 2015

C++11 and initialization

Uniform initialization in C++11 can be tricky.

Invocations mean something completely different and also give different results:

std::vector<int> v(1); // "normal" constructor invocation with (int) param - creates vector<int> with 1 element initialized to default value (i.e. 0)
std::vector<int> v{1}; // invocation of constructor with initializer_list<> param - content of initializer_list is copied into vector (i.e. one value of 1)


Following invocations also mean something completely different and give different results:

std::vector<int> v(1, 1); // "normal" constructor invocation with (int,int) params - creates vector<int> with 1 element initialized to specified value value (i.e. 1)
std::vector<int> v{1, 1}; // invocation of constructor with initializer_list<> param - content of initializer_list is copied into vector (i.e. two values of 1)


But following mean something completely different but give same results:

std::vector<int> v(2, 2); // "normal" constructor invocation with (int,int) params - creates vector<int> with 2 elements initialized to specified value value (i.e. 2)
std::vector<int> v{2, 2}; // invocation of constructor with initializer_list<> param - content of initializer_list is copied into vector (i.e. two values of 2)


Note that following will not compile:

std::vector<int> v(1, 1, 1); // no such "normal" constructor

whereas following is completely fine C++11 statement:

std::vector<int> v{1, 1, 1}; // invocation of constructor with initializer_list<> param - content of initializer_list is copied into vector (i.e. three values of 1)


Also note what is perhaps even more surprising that when container value type cannot be initialized from values in the list (no such conversion), then following construction will invoke "normal" constructor:

std::vector<std::string> v{1}; // same as - std::vector<std::string> v(1);


To avoid such behavior assign can be used in initialization (this is still construction, not assignment):

std::vector<std::string> v = {1}; // this will fail to compile
std::vector<int> v = {1}; // this will invoke initializer_list<> constructor as for std::vector<int> v{1};


There is even more about uniform initialization, especially using "auto" keyword - please check e.g. "Effective Modern C++" by Scott Meyers.
Also please check stackoverflow.

poniedziałek, 9 listopada 2015

Thread-safe Catch

Catch test framework is nice, but not thread-safe - see https://github.com/philsquared/Catch/issues/99

There is thread-safe fork of Catch https://github.com/ned14/Catch-ThreadSafe
At the time of writing this original Catch is 1.2.1 whilst thread-safe fork 1.1

piątek, 6 listopada 2015

With or without you (exceptions)

To exception, or not to exception, that is the question.
What about cyclomatic complexity argument? E.g. http://programmers.stackexchange.com/questions/219872

piątek, 28 sierpnia 2015

upgradeable RW-locks - no, no

Never to be forgotten - upgradeable RW-locks always lead to deadlock.
I.e. when reader upgrades to writer without first leaving read lock, then other tread doing same lead to deadlock - no one moves back - deadlock.
Therefore:
- do not think on upgradeable RW-locks,
- if do so, then try-upgrade() function might be good approach, or
- deadlock detection, or
- 3rd user type - beside reader and writer - upgreadeableReader (like EnterUpgradeableReadLock from .NET). There can be only one upgreadeableReader (mutually exclusive). Normal readers cannot upgrade, therefore it is certain that only one user-reader will try to upgrade.

Redirect tcp to console (file) with awk

Sometimes useful, esp. when redirecting local tcp process output to console (file):

BEGIN {
NetService = "/inet/tcp/0/localhost/finger"
print "name" |& NetService
while ((NetService |& getline) > 0)
print $0
close(NetService)
}

More info @http://www.gnu.org/software/gawk/manual/gawkinet/gawkinet.html#Making-Connections

QNX specific commands

List of interesting (subjective) QNX-specific commands
  • on - usually used for 2 reasons: start new process with specified priority and/or start new process on specific node (it makes possible to start process on different processor/system running QNX - working qnet is required - see Asymmetric multiprocessing (AMP))
  • pidin - process list, frequently more useful than ps, top (e.g. options "-f A", "-f n","threads", "memory", "fds")
  • coreinfo - allows for preliminary corefiles analysis directly on target without using gdb (note that in QNX coredumps are produced by dumper)
  • use - info about specific command (e.g. "use devf-generic", "use -i devf-generic" - for build version)
  • sendnto e.g. "sendnto -d /dev/ttyUSB1 qnx-ifs" (together with "cat /dev/ttyUSB1" and "echo 's' >/dev/ttyUSB1")

piątek, 20 lutego 2015

Virtualbox, linux, remote desktop, NAT

Enable NAT in VB machine network settings, set port mapping e.g. SOME_HOST_PORT->3389 (remote desktop) and SOME_HOST_PORT->22(ssh)
To start VB as windows service use vboxvmservice.

References
http://vboxvmservice.sourceforge.net/
http://support.microsoft.com/kb/304304/
http://code.google.com/p/phpvirtualbox/
http://code.google.com/p/virtualboxservice/
http://www.techques.com/question/2-188105/Virtualbox-Start-VM-Headless-on-Windows
http://www2.ece.ohio-state.edu/computing/rdpssh.html
https://help.ubuntu.com/community/SSH/OpenSSH/PortForwarding

poniedziałek, 9 lutego 2015

non-intrusive compile-time types registration



Note - above does not work with VS compilers.
Generally this approach should be avoided, but nice to know:)

sobota, 31 stycznia 2015

What's nice there

eTrice provides an implementation of the ROOM (Real-Time Object-Oriented Modeling) modeling language together with editors, code generators for Java, C++ and C code and exemplary target middleware.
The model is defined in textual form (Xtext) with graphical editors (Graphiti) for the structural and behavioral (i.e. state machine) parts.
http://www.eclipse.org/etrice/

Trace Compass is a Java tool for viewing and analyzing any type of logs or traces. Its goal is to provide views, graphs, metrics, etc. to help extract useful information from traces, in a way that is more user-friendly and informative than huge text dumps.
http://projects.eclipse.org/projects/tools.tracecompass


https://developers.google.com/web/fundamentals/


FlatBuffers is a serialization library for games and other memory constrained apps.
https://github.com/google/flatbuffers

Protocol Buffers - Google's data interchange format.
https://github.com/google/protobuf

The C++ Network Library Project -- header-only, cross-platform, standards compliant networking library.
https://github.com/google/cpp-netlib

A fast compressor/decompressor.
https://github.com/google/snappy

Brotli compression format.
https://github.com/google/brotli

Fruit is a dependency injection framework for C++.
https://github.com/google/fruit

RE2 is a fast, safe, thread-friendly alternative to backtracking regular expression engines like those used in PCRE, Perl, and Python. It is a C++ library.
https://github.com/google/re2

redgrep is a grep based on regular expression derivatives.
https://github.com/google/redgrep

Gumbo is an implementation of the HTML5 parsing algorithm implemented as a pure C99 library with no outside dependencies.
https://github.com/google/gumbo-parser

lmctfy is the open source version of Google’s container stack, which provides Linux application containers.
https://github.com/google/lmctfy

Lovefield is a relational query engine built on top of IndexedDB. It provides SQL-like syntax and works cross-browser (currently supporting Chrome 37+, Firefox 31+, and IE 10+).
https://github.com/google/lovefield

codefmt is a utility for syntax-aware code formatting. codefmt relies on codefmtlib for registration and management of formatting plugins.
https://github.com/google/vim-codefmt

Cppcheck is a static analysis tool for C/C++ code. Unlike C/C++ compilers and many other analysis tools it does not detect syntax errors in the code. Cppcheck primarily detects the types of bugs that the compilers normally do not detect. The goal is to detect only real errors in the code (i.e. have zero false positives).
http://cppcheck.sourceforge.net/

pugixml is a light-weight C++ XML processing library (it has XPath 1.0 implementation for complex data-driven tree queries).
http://pugixml.org/

Modern, powerful open source C++ class libraries for building network- and internet-based applications
http://pocoproject.org/

Multi-paradigm automated test framework for C++ and Objective-C (and, maybe, C). It is implemented entirely in a set of header files, but is packaged up as a single header for extra convenience.
https://github.com/philsquared/Catch

Some interesting C++ articles e.g. small size containers optimization using custom allocator
http://howardhinnant.github.io/

Gold linker
https://en.wikipedia.org/wiki/Gold_(linker)

Warp preprocessor
https://github.com/facebook/warp

LevelDB is a fast key-value storage library written at Google that provides an ordered mapping from string keys to string values.
https://github.com/google/leveldb

Kyoto Cabinet is a library of routines for managing a database.
http://fallabs.com/kyotocabinet/

UnQLite is a in-process software library which implements a self-contained, serverless, zero-configuration, transactional NoSQL database engine.
http://unqlite.org/

A Fast Key-Value Storage Engine Based on Hierarchical B+-Tree Trie
https://github.com/couchbase/forestdb

LMDB is an ultra-fast, ultra-compact, crash-proof key-value embedded data store
http://symas.com/mdb/

SQLite4 (with LSM - embedded database library for key-value data)
https://sqlite.org/src4/doc/trunk/www/index.wiki

FineDB.org - A high-performance noSQL database
http://www.finedb.org/

High performance JSON manipulation library
https://github.com/couchbase/subjson

Highly portable C system library
https://github.com/saprykin/plibsys

Memory optimal Small String Optimization implementation for C++
https://github.com/elliotgoodrich/SSO-23

c2xml is a tool that generates a XML representation of pre-processed ANSI C source code
http://c2xml.sourceforge.net/

Fake Function Framework (fff)
https://github.com/meekrosoft/fff

niedziela, 18 stycznia 2015

Problem with Bluetooth in Dell Precision M4600
No connection neither from Linux nor Windows 7. The point is everything worked properly some time ago. Now Bluetooth seems to work and find devices, but after connection attempt it is broken instantly.
'hciconfig' shows device properly and from 'bluetoothctl', command 'paired-devices' shows devices properly.
Then using 'connect <dev>' everything worked again.

sobota, 1 listopada 2014

Fundamental types initialization

Consider something as complicated as:

struct A
{
   int f; 
};

the problem is value of member 'f'.
Structure A is of course POD therefore rules for member initialization can be really tricky.
Differences comes from three sources:
- way of initalization,
- C++ standard version,
- compiler vendor.

Possible ways of initialization are:
A;
A();
A{};
which should be same to version with dynamic allocation:
new A;
new A();
new A{};

Note two things:
- it is impossible to use second case directly i.e.:
A a();
because in C++ this is function declaration (declaration can appear also inside function body).
To use second initialization method, syntax can be:
A a = A();
- third way of initialization is from C++11 and allows for:
A a{};

Initialization of fundamental type variables and PODs is subject of constant changes and obscurity between C++ standards.
In C++98 initialization of non-POD object without constructor (e.g. struct with desctructor only or inherited) does not initialize fundamental type fields to 0 (but as it is visible below it is not truth for current compilers).
This was changed in C++03.
Also compilers can introduce surprising behaviours. VSC++ (before version 2013) was famous of not initializing PODs with A() syntax (still visible for some cases).

Below are test results of initialization results for different types and compilers.
Cases are
  1. fundamental type,
  2. simplest POD struct,
  3. simplest non-POD struct (destructor added),
  4. non-POD struct with field default initialization in constructor,
  5. non-POD struct without field initialization in constructor,
  6. non-POD struct with inheritance and no constructors,
  7. non-POD struct with inheritance and field default initialization in base class constructor,
  8. non-POD struct with inheritance and field default initialization in derived class constructor.

Compilers used
  • gcc 4.8.2
  • clang 3.3
  • VisualStudio C++ 2013

1. fundamental type
init method g++ std=c++11 g++ std=c++03 g++ std=c++98 clang++ std=c++11 clang++ std=c++03 clang++ std=c++98 VSC++2013
int a; - - - - - - -
int a = int(); 0 0 0 0 0 0 0
int a{}; 0 n.a. n.a. 0 n.a. n.a. 0
int *a = new int; - - - - - - -
int *a = new int(); 0 0 0 0 0 0 0
int *a = new int{}; 0 n.a. n.a. 0 n.a. n.a. 0


2. simplest POD struct
struct A
{
   int f; 
};
init method g++ std=c++11 g++ std=c++03 g++ std=c++98 clang++ std=c++11 clang++ std=c++03 clang++ std=c++98 VSC++2013
A a; - - - - - - -
A a = A(); 0 0 0 0 0 0 0
A a{}; 0 n.a. n.a. 0 n.a. n.a. 0
A *a = new A; - - - - - - -
A *a = new A(); 0 0 0 0 0 0 0
A *a = new A{}; 0 n.a. n.a. 0 n.a. n.a. 0


3. simplest non-POD struct (destructor added)
struct A
{
   ~A() {}
   int f; 
};
init method g++ std=c++11 g++ std=c++03 g++ std=c++98 clang++ std=c++11 clang++ std=c++03 clang++ std=c++98 VSC++2013
A a; - - - - - - -
A a = A(); 0 0 0 0 0 0 -
A a{}; 0 n.a. n.a. 0 n.a. n.a. 0
A *a = new A; - - - - - - -
A *a = new A(); 0 0 0 0 0 0 -
A *a = new A{}; 0 n.a. n.a. 0 n.a. n.a. 0


4. non-POD struct with field default initialization in constructor
struct A
{
   A() : f() {}
   int f; 
};
init method g++ std=c++11 g++ std=c++03 g++ std=c++98 clang++ std=c++11 clang++ std=c++03 clang++ std=c++98 VSC++2013
A a; 0 0 0 0 0 0 0
A a = A(); 0 0 0 0 0 0 0
A a{}; 0 n.a. n.a. 0 n.a. n.a. 0
A *a = new A; 0 0 0 0 0 0 0
A *a = new A(); 0 0 0 0 0 0 0
A *a = new A{}; 0 n.a. n.a. 0 n.a. n.a. 0


5. non-POD struct without field initialization in constructor
struct A
{
   A() {}
   int f; 
};
init method g++ std=c++11 g++ std=c++03 g++ std=c++98 clang++ std=c++11 clang++ std=c++03 clang++ std=c++98 VSC++2013
A a; - - - - - - -
A a = A(); - - - - - - -
A a{}; - n.a. n.a. - n.a. n.a. -
A *a = new A; - - - - - - -
A *a = new A(); - - - - - - -
A *a = new A{}; - n.a. n.a. - n.a. n.a. -


6. non-POD struct with inheritance and no constructors
struct P
{
   int g;
};
struct A : public P
{
   int f;
};
init method g++ std=c++11 g++ std=c++03 g++ std=c++98 clang++ std=c++11 clang++ std=c++03 clang++ std=c++98 VSC++2013
A a; f:-, g:- f:-, g:- f:-, g:- f:-, g:- f:-, g:- f:-, g:- f:-, g:-
A a = A(); f:0, g:0 f:0, g:0 f:0, g:0 f:0, g:0 f:0, g:0 f:0, g:0 f:-, g:-
A a{}; f:0, g:0 n.a. n.a. f:0, g:0 n.a. n.a. f:-, g:-
A *a = new A; f:-, g:- f:-, g:- f:-, g:- f:-, g:- f:-, g:- f:-, g:- f:-, g:-
A *a = new A(); f:0, g:0 f:0, g:0 f:0, g:0 f:0, g:0 f:0, g:0 f:0, g:0 f:0, g:0
A *a = new A{}; f:0, g:0 n.a. n.a. f:0, g:0 n.a. n.a. f:-, g:-


7. non-POD struct with inheritance and field default initialization in base class constructor
struct P
{
   P() : g() {}
   int g;
};
struct A : public P
{
   int f;
};
init method g++ std=c++11 g++ std=c++03 g++ std=c++98 clang++ std=c++11 clang++ std=c++03 clang++ std=c++98 VSC++2013
A a; f:-, g:0 f:-, g:0 f:-, g:0 f:-, g:0 f:-, g:0 f:-, g:0 f:-, g:0
A a = A(); f:0, g:0 f:0, g:0 f:0, g:0 f:0, g:0 f:0, g:0 f:0, g:0 f:-, g:0
A a{}; f:0, g:0 n.a. n.a. f:0, g:0 n.a. n.a. f:-, g:0
A *a = new A; f:-, g:0 f:-, g:0 f:-, g:0 f:-, g:0 f:-, g:0 f:-, g:0 f:-, g:0
A *a = new A(); f:0, g:0 f:0, g:0 f:0, g:0 f:0, g:0 f:0, g:0 f:0, g:0 f:-, g:0
A *a = new A{}; f:0, g:0 n.a. n.a. f:0, g:0 n.a. n.a. f:-, g:0


8. non-POD struct with inheritance and field default initialization in derived class constructor
struct P
{
   int g;
};
struct A : public P
{
   A() : f() {}
   int f;
};
init method g++ std=c++11 g++ std=c++03 g++ std=c++98 clang++ std=c++11 clang++ std=c++03 clang++ std=c++98 VSC++2013
A a; f:0, g:- f:0, g:- f:0, g:- f:0, g:- f:0, g:- f:0, g:- f:0, g:-
A a = A(); f:0, g:- f:0, g:- f:0, g:- f:0, g:- f:0, g:- f:0, g:- f:0, g:-
A a{}; f:0, g:- n.a. n.a. f:0, g:- n.a. n.a. f:0, g:-
A *a = new A; f:0, g:- f:0, g:- f:0, g:- f:0, g:- f:0, g:- f:0, g:- f:0, g:-
A *a = new A(); f:0, g:- f:0, g:- f:0, g:- f:0, g:- f:0, g:- f:0, g:- f:0, g:-
A *a = new A{}; f:0, g:- n.a. n.a. f:0, g:- n.a. n.a. f:0, g:-


Legend
  • "0" - initialized to 0
  • "-" - not initialized
  • "n.a." - available only in C++11

And what lesson comes form data above - to be really sure field is initialized, you have to explicitly use initialization construct for the field (in constructor initialization list).

Test application available for downlowad here. Please note placement new used to avoid false 0-positive answers. For stack allocated items it is not that easy - there is try with recursive function (to pollute stack with non 0 values) but it is not always enough (false 0 answers can happen).

Note that in VSC++2013 "__cplusplus" is defined as 199711 (like for C++98 standard) but compiler allows for C++11 usage (perhaps not complete and therefore "__cplusplus" is not defined as 201103).

wtorek, 19 sierpnia 2014

Acoustics absorption calculation (impedance tube)

Here is bunch of equations to calculate acoustic absorption coefficient according to transfer function method (ISO 10534-2:1998).
Absorption coefficient as function of frequency can be calculated from pressure reflection factor with:

Reflection factor is calculated from calculation (corrected) transfer function:
where 's' is microphones' spacing, 'x1' is distance form specimen to closer microphone and 'k0' is wave number.

Calculation (corrected) transfer function comes from:

Correction transfer function is obtained from:

and calculated as:

Please note that absorption coefficient calculation does not really need 'x1' distance to be known.
This is visible when following substitution is used in equation for reflection factor:

Then square of absolute value is given as (which is free from 'x1'):

Taking above into account ready to use equation can be derived:

taking following into account:

can be simplified to:

where:


Note that calculations are a bit simpler using polar representation for complex numbers.

niedziela, 3 sierpnia 2014

Real time (stream) acquisition with ADS1278 and MMB0 (ADS1278EVM-PDK)

MMB0 with ADS1278 board is perfect tool to start adventure with DSP programming, especially in A/D conversion context.

Solution presented below is development of first Linux approach presented here.

ADS1278EVM-PDK is delivered with ready to use Windows software called ADCPro which is post processing tool for data gathered. The tool is build using LabVIEW environment and allows for basic estimation of A/D converter features and performance.
Main weakness of ADCPro (which is of course out of its original purpose) is lack of data streaming handling. Data acquisition is realized within MMB0 using its 16MB SDRAM memory. After acquisition is finished, data is transferred to PC for further analysis and presentation. This of course limits length of data that can be acquired in single measurement.
It is tempting idea to create alternative software to provide data streaming from MMB0 functionality. Obvious limitation here is USB 1.1 used in TMS320VC5509A which drives MMB0 (Rev.D in my case).
For USB 1.1 bandwidth is practically limited to about 1MB/s, which does not allow for all 8 channels utilisation with high sample rate. But this limitation makes the problem even more attractive - try to get all possible performance from MMB0 and check limits of USB 1.1.

Prepared solution contains two parts: firmware for MMB0 prepared with free Linux version of CCS and simple PC (Linux) app for control and data acquisition.
In order to limit usage of precious bandwidth data samples transferred to PC are 24-bit length (1/4 less than original 32-bit samples). As 24-bit is native resolution of ADS1278 therefore this has no impact on measurement precision (no real downsampling).
Also transfers are performed using maximal possible buffer size for BULK transfers (close to TMS320VC5509A's limit 64kB) which gives maximal performance.
As MMB0 has 16MB of SDRAM memory it gives additional advantage when handling short time gathering even for sampling rates out of USB 1.1 transfer possibilities.
SDRAM used as cyclic buffer stores data before transfer and in case of overflow acquisition is stopped, but gathered data can be transferred to PC. Please also note that due to transfer being parallel to acquisition real acquisition length is more than SDRAM size (some data is transferred and additional acquisitions can be stored before overflow takes place).
As SDRAM buffer usage is critical parameter for application performance, MMB0's led segment is used to present digit which represents decimals of buffer usage (and letter 'o' in case of overflow).


Fig.1 MMB0 with ADS1278 board - buffer usage 0-9%

To gather data transferred using USB interface, simple app was developed. The app handles start and stop commands and stores gathered data to a file.
Application parameters allows for easy setup i.e. to specify cpu clock (via APLL divider and multiplier), 5509 output clock divider, also settings for external PLL (for ADS1278 clock) shall be specified (multiplier and dividers). The settings allows for arbitrary sample rate selection.
Beside clocks ADS operating settings shall be specified i.e. CLKDIV 1 or 0 and mode (highspeed, highresolution, lowpower or lowspeed).


Fig.2 Acquired sine wave signal for channel 4

Here are results obtained for maximal transfer rates for each mode (acquisition time before overflow occurs)

  • High-speed mode, 8ch, 144500 SPS, cpu_freq: 192 MHz (m: 16, d: 1, div: 2), ADS f_clk=36.992 MHz (p: 289, q: 75, post: 10)
    max acquisition time ~6.5 sec, acquired 22866480 bytes (in 21.8 sec)
  • High-resolution mode, 8ch, 52725 SPS, cpu_freq: 192 MHz (m: 16, d: 1, div: 4), ADS f_clk=26.9952 MHz (p: 703, q: 125, post: 10)
    max acquisition time ~70 sec, acquired 89107200 bytes (in 85.7 sec)
  • Low-power mode (CLKDIV = 1), 8ch, 52725 SPS, cpu_freq: 192 MHz (m: 16, d: 1, div: 4), ADS f_clk=26.9952 MHz (p: 703, q: 125, post: 10)
    max acquisition time ~63 sec, acquired79541280 bytes (in 78.6 sec)
  • Low-power mode (CLKDIV = 0), 8ch, 52725 SPS, cpu_freq: 192 MHz (m: 16, d: 1, div: 4), ADS f_clk=13.4976 MHz (p: 703, q: 100, post: 25)
    max acquisition time ~63 sec, acquired 79541280 bytes (in 78.5 sec)
  • Low-speed mode (CLKDIV = 1), 8ch, 10545 SPS, cpu_freq: 192 MHz (m: 16, d: 1, div: 4), ADS f_clk=26.9952 MHz (p: 703, q: 125, post: 10)
    no overflow occurred, continuous streaming possible, average transfer rate ~250kB/s
  • Low-speed mode (CLKDIV = 0), 8ch, 10545 SPS, cpu_freq: 192 MHz (m: 16, d: 1, div: 4), ADS f_clk=5.39904 MHz (p: 703, q: 125, post: 50)
    no overflow occurred, continuous streaming possible, average transfer rate ~250kB/s


Generally maximal sampling which can be performed without overflow (or with overflow after long time) is about 45kSPS (for 8 channels).


Please note that other devices connected to USB host may influence bandwidth for transfer. Also I have noticed with my computer that USB 2.0 host has better max throughput for USB 1.1 connection than USB 3.0 host.


TODO list:
  1. Add downsampling to 16-bit option for further bandwidth save and higher sampling rates handling.
  2. Add possibility to limit number of (or select) channels transferred to have even more bandwidth saving.
  3. Implement as Linux (and Windows) driver.

poniedziałek, 6 stycznia 2014

gcc link-time optimization

Link optimization can give impressive results (at least regarding executable size as presented below).
Here is output from simple program build. The program consists of 3 modules and 2 header files (6 functions in total).
  • Normal compilation (and linking), no optimization 'gcc mod1.c mod2.c mod3.c -o test'
    stripped executable size - 14480.
  • Normal compilation (and linking), optimized for size 'gcc mod1.c mod2.c mod3.c -o test -Os'
    stripped executable size - 10384.
  • LTO compilation (and linking), no optimization 'gcc mod1.c mod2.c mod3.c -o test -flto'
    stripped executable size - 10384.
  • LTO compilation (and linking), optimized for size 'gcc mod1.c mod2.c mod3.c -o test -flto -Os'
    stripped executable size - 6288.
GCC version used 4.8.2 (x86-64).

Please note that compilation time and output code speed was not taken into account in simple example consideration above.
Also for sure example is far too simple to treat it as meaningful case, please treat it just as remark of LTO possibilities.

References

  1. gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html#index-flto-934
  2. gcc.gnu.org/wiki/summit2010?action=AttachFile&do=get&target=hubicka.pdf
  3. en.wikipedia.org/wiki/Link-time_optimization