Easy CRC checksums with Boost

The Boost CRC library makes it painless to compute the CRC checksum on data.  For HDL designers, the library can be useful in generating test vectors for use in testbenches for CRC modules.  The Boost documentation provides a complicated example program that shows how to use the library, but I stripped it down to create an even simpler example of how to use do a CCITT CRC-16 checksum.

#include <boost/crc.hpp>
#include <boost/integer.hpp>
#include <cassert>

int main(int argc, char *argv[])
{
  unsigned char const test_data[] = { 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39 };
  std::size_t const test_data_len = sizeof(test_data) /   sizeof(test_data[0]);
  boost::uint16_t const expected_result = 0x29B1;

  boost::crc_ccitt_type checksum_agent;
  checksum_agent.process_bytes(test_data, test_data_len);

  assert(checksum_agent.checksum() == expected_result);
  return 0;
}

Using C++0x features with g++

With the announcement recently that the C++0x spec has finally been finalized–I suppose it should be called C++11 at this point–I will now try to learn more of the new features that will be available.  I happy that much of what I currently use in Boost will become standardized (such as shared_ptr, threads, etc.)

Just as an FYI to myself, to play with C++0x features in g++, add the “-std=gnu++0x” compiler option.  For example, it get the following program to build:

// decltype.cpp
int f() { return 0; }

int main()
{
   decltype(f()) i = 8;
   return 0;
}

use the following on the command line:

g++ -std=gnu++0x decltype.cp

Final Thoughts on Ada

I’ve been dabbling with Ada off and on for the past three years now.  It has been very interesting and it has changed the way I think about software.  That said, I think I am letting it go now.  Let me explain.

I have been working on a model and software tool for a ASIC design course I’m taking this semester.   Essentially I need to do some preprocessing of data that is to be stored in a ROM in the hardware.  We are free to use any technology to implement the software part, and I was torn between C++ and Ada initially.  I’m most proficient and productive in C++, but I thought it would be a good opportunity to really learn how to use Ada in a non-trivial way.

I ended up picking Ada, and at first all was well.  The compiler caught a lot of silly errors and the algorithms just seemed to flow.  Despite my unfamiliarity with Ada, the syntax felt intuitive and I did not run into too many issues implementing my algorithms. I particulary apprecaited the assignment operator (:=) and wished for it in C++ at a later point.  Exceptions when dereferencing my pointers was also much more pleasant than core dumps and gdb sessions.

Ada let me down in three areas however: strings, text I/O, and generic containers.  Working with strings and text in Ada is just down-right painful, and I think Ada really shows its age here.  The I/O subsystem is also as primitive as its gets, and something as simple as printing an integer as a hexadecimal number without the 16#…# was not easy and I ended up having to writing somewhat of a hack.  I am sure there is a better way, but there just isn’t a large enough community and Internet pressence around Ada to quickly figure out the better way to do things.

Generics in Ada were also quite awkward to work with.  The most annoying aspect about generics is the having to use package methods to operate on the generic objects.  The containers package also lacks some very fundamental data structures such as simple queues.  In general I don’t like generics in Ada, they feel like an afterthought and a poor immitation of the Standard Template Library of C++.  I realize there are third party libraries like the Booch Components or Charles Library, but to a novice Ada developer I found it difficult to build and install things with GPR files rather than Makefiles.

In the end, I reverted back to C++.  Despite the cryptic nature of C++ and a frustrating debugging session where the cause was “if( a = b)”–which Ada would have caught–I was able quickly reimplement the code in C++ and move onto the hardware design…the reason for enrolling in a hardware design course.  Where C++ really shined was with the STL and Boost library.  STL containers and algorithms are simple to use, and Boost shared_ptr saves one from having to worry about memory management and allows one to focus on algorithms and the problem at hand.  And program_options makes creating a command line program a breeze.

I am sure that Ada really shines in embedded systems where string processing is much less common, and the features of Ada are in high demand. To master Ada, I also think one would need access to a strong mentor as the books and available resources for Ada are lacking in this day and age.

I came to appreciate many featuers in Ada, but in the end I just do not think it is the right tool for the type of things I do at work, school, and home.  C++ does everything I need at the momement, and I should probably focus my attention and software energies on learning new C++0x features or even exploring Erlang, my favorite programming technology at the moment.

Boost: Thread timing and timeouts

Boost.Thread has the ability to use timeouts for obtaining mutex resources or even just blocking a thread with the sleep() method.  Creating a timeout is, thankfully, a very easy task. All one needs to know is that the Boost.Thread library takes timeout parameters in the form of boost::system_time (as of Boost 1.35).  This is actually just a simple typedef to a POSIX data structure in the Boost.DateTime library.  From boost/thread/thread_time.hpp:

typedef boost::posix_time::ptime system_time;

To create a simple timeout, the following code will usually suffice:

boost::system_time timeout = boost::get_system_time() + boost::posix_time::milliseconds(n);

The vaule for n is simply an integer value, perhaps randomly generated? There is no need to dig into the large and versatile Boost.DateTime library, and with boost::system_time there is no longer a need to use boost::xtime unless working with an older code base that has yet to be refactored.  With random time period generation and timeouts covered, we are now ready to move onto exploring some multithreaded code.

Boost: a random time period generator

Random numbers play a critical role in the verification of designs, allowing testers to apply stimuli and stress a system beyond the known boundary conditions.  The C++ standard library supplies the random() function, which after seeding, produces a simple pseudo-random sequence.  For many applications, this simple function is enough; alternatively, it is very limiiting if your application needs to grow and support different testing methods.  Though there are many random number libraries freely available, most modern C++ applications utilize Boost, and the Boost libraries contain the Boost.Random library as a compile-only header library.

A glance in the boost/random/ directory can be intimidating at first.  There are various header files with cryptic mathematical names, but at its heart, however, the library is easy to understand once you understand the background concepts and have a statistical reference at your side. There are two key concepts that you need to understand before setting out to use the library: generators and distributions.

Background

Based on the Boost.Random documentation, generators can be classified into roughly three variations:

  • Uniform – number sequences uniformly distributed over a finite range
  • Pseudo – numbers sequences generated by an algorithmic process that simulates random behavior
  • Non-deterministic – number sequences generated by stochastic processes

Determining which type of generator is best for your application depends on many factors, but for most test applications the pseudo-random generator is adequate.  Examples of the pseudo-random generators are minstd_rand and rand48, which are both declared in boost/random/linear_congruential.hpp.  Refer to the boost documentation and header files for more information on the various generators available.

Distributions represent the distribution, or layout, of a sequence of numbers over finite interval based on the corresponding random variable of the same name.  When selecting a distribution for your tests, refer to an undergraduate level Statistics textbook or your favorite statistical reference. Boost.Random supports a large number of statistical distributions, including, but not limited to:

  • Normal
  • Uniform
  • Binomial
  • Exponential
  • Gamma
  • Bernoulli
  • Geometric
  • Poisson

If you need a distribution or generator not included in Boost.Random, you can implement new classes that conform to the Boost.Random interface causing minimal change to your code. More often than not, the library already has a sufficient amount at your disposal.  Popular pseudo-random generators, such as the linear feedback shift that is ubiquitous in hardware engineering (boost/random/linear_feedback_shift.hpp) are available out-of-the-box and ready to use with some simple template parameters at instantiations.

In the remainder of this post, I am going to demonstrate the use of generators and distributions in developing a simple class that generates pseudo-random numbers for time periods.

Generating Random Time Periods

When testing multi-threaded code or even just trying to understand concepts in the Boost.Threads library, I find that having the ability to quickly and easily generate random time intervals beneficial.  One thread can be blocked for X milliseconds, another by Y milliseconds, allowing one to verify the behavior of the various synchronization mechanisms in Boost.Threads.  Using boost::variate_generator, we can bind a generator to a distribution and create a random sequence of numbers representing time periods.  I use a simple class like the RandomTimePeriod class listed below.

#ifndef RANDOMTIMEPERIOD_H
#define RANDOMTIMEPERIOD_H
#include <boost/random.hpp>
#include <boost/shared_ptr.hpp>

class RandomTimePeriod
{
private:
  // accept default template param of 'int'
  typedef boost::uniform_int<> distribution_type;
  typedef boost::minstd_rand   generator_type;
  typedef boost::variate_generator< generator_type,
            distribution_type > RandomNumberGenerator;

public:
  RandomTimePeriod(int max_ms=100)
  {
    // Magic number 42 - if you don't understand this,
    //    look into Douglas Adams--now!
    generator_type generator(42);
    distribution_type distribution(0,max_ms);
    _rng.reset(new RandomNumberGenerator(generator, distribution));
  }

  int next()
  {
    (*_rng)();
  }

private:
  boost::shared_ptr _rng;
};
#endif

The code above should be rather straightforward.  Typedefs are used to make the constructor code more readable.  The constructor takes a parameter specifying the max time period in milliseconds, and it constructs the random number generator member variable.  The generator is passed the infamous value of 42 as its seed value, but in real test code one should provide a better method of obtaining a seed.  Calling the next() method on a RandomTimePeriod object will return a pseudo-random number. Internally the random number generator is stored in a smart pointer so that when the object’s reference count reaches zero, the object is properly cleaned up.  Very simple, right?  The following driver program demontrates how to use the RandomTimePeriod class.

int main(int argc, char* argv[])
{
  RandomTimePeriod rtp;
  for( int i=0; i<25; ++i){
    std::cout << rtp.next() << std::endl;
  }
  return 0;
}

Armed with a simple random number generator, we can now focus on creating better tests for the verification of our designs.  Stay tuned for more tutorials on Boost libraries, including Boost.Thread.

C++ gotcha

I came across an amusing example in Meyers’ Effective STL Item 6***.

class Widget { ... };
Widget w();

As Meyers explains,  it seems like the default constructor is called. However, in C++ this second line is actually declaring a function ‘w’ that takes no parameters and returns a ‘Widget’. If the code author intended for the constructor to be called, he would have to write:

class Widget { ... };
Widget w;

I chuckled to myself after I saw this because the former will cause the Java compiler to get angry. This is another example of how you have to pay attention when you write C++.

*** I love Meyer’s works and his writing style.  He writes to you as a professional and an equal, even though he is a master.

Lock-Free Queue articles on Dr. Dobbs Journal

There are not a lot of websites and resources for C++ news these days.  Occasionally, Dr. Dobb’s Journal has some interesting articles, such as the Concurrent Queue seiries. So far there are three articles in response to the original idea, and it looks like more are to follow.

Lock-Free Queues – original idea for a lock-free queue
Lock-Free Code: A False Sense of Security – Herb Sutter’s first in a series of articles on a concurrent queue implementation
Writing Lock-Free Code: A Corrected Queue – Herb Sutter’s second article in the series
Writing a Generalized Concurrent Queue – Herb Sutter’s third article in the series
Somewhat related, there are also some interesting articles on threading as well:

What’s New in Boost Threads by Anthony Williams
Managing Application Thread Use by Levent Akyil
The Trouble With Locks – an older article by Herb Sutter on locks

Get up to speed on C++0x multithreading

DevX is running an artcile titled Simpler Multithreading in C++0x by Andrew Williams.  It is a very good introduction the multithreading supported that is to be present in C++0x.

“C++ Concurrency in Action” coming next year

Anthony Williams, author of the Boost threads library, is writing a book on C++ threading based on the upcoming thread support to be added to C++0x.  I am definitely going to pick it up when it comes out on paper.  Hopefully by the time the book comes out, the compiler developers will have a robust implementation of the threading libraries.

After years of messing with PThreads and Win32 threads, Boost threads have really made my life easier.  Boost threads are simple and they sure help make your code a lot more readable.  The only problem with Boost is that you have to install it separately and that can require a lot of researching and trial-and-error on older hardware and non-standard architectures.  It will be nice to have threading built into the language standard like in Ada and Java.

Boost 1.36 and Sun Studio 12

Trying to get Boost and Sun Studio C++ compilers to place nice on Ultrasparc processors isn’t exactly straight-forward.  I fought with both Sun CC and g++, and after browsing mailing lists of Boost and other C++ software, reading various blogs at Sun, and through brute force effort, I managed to build Boost 1.36 for Sun CC.  I just have to add that it was a lot easier getting Boost to build on Mac OS X with g++!  I’m sure someone will say it I’m and idiot since I couldn’t get it to work ont he first try, but let me just say that it was not obvious.  I did a lot of reading and still did not come away with a definitive answer.  The guys at Sun ought to create a Wiki for both Sun Studio users and Sun engineers to share information on working with Boost.

Before I get into the build process, here is the build environment I used just for reference:

# uname -a
SunOS radium 5.10 Generic_137111-02 sun4u sparc SUNW,Sun-Blade-100

# CC -V
CC: Sun C++ 5.9 SunOS_sparc Patch 124863-06 2008/07/08

Of course it is always a good idead to make sure your Sun Studio patches are up-to-date before you start.  The build process I used is listed below.

1. Build a custom version of Bjam for your machine.  Download it from Boost’s sourceforge portal and follow the install directions.  It builds painlessly and installs itself in /usr/bin by default.

2. After downloading and unarchiving Boost 1.36 to a stating platform–I used /opt–change your working directory to the Boost root directory and run the configuration script.  Run ./configure –help to see the various options.  I used the following to specify the location of bjam, the compiler to use, and finally where to put everything in the end:

./configure –with-bjam=/usr/bin/bjam –with-toolset=sun –prefix=/opt

It is important to specify the compiler if you have both g++ and Sun CC in your path environment variable.  On a default developer’s install of Solaris 10, you have g++ in /usr/sfw/bin and then if you installed Sun Studio 12, a symlink is placed in /usr/bin that points to CC.  Be careful!

3. Configure your user-config.jam file which is used by Bjam when building Boost.  After running the configure script, my user-config.jam looked like this:

# Boost.Build Configuration
# Automatically generated by Boost configure

# Compiler configuration
using sun ;

# Python configuration
using python : 2.4 : /usr ;

I added some flags for the compiler to fix a lot of the error messages I was getting when I would run the make process.  The modified file looks like this:

# Boost.Build Configuration
# Automatically generated by Boost configure

# Compiler configuration
using sun : 5.9 : /opt/SUNWspro/bin/CC : <stdlib>sun-stlport <link-flags>-library=stlport4 <cxxflags>-native64 ;

# Python configuration
using python : 2.4 : /usr ;

I should add that I don’t know if this is necessary based on step four in my process.  I really did not feel like trying to hack around the build process as it is complicated and honestly, I want to work on my application, not on becoming a guru Boost builder.  I made this changes because it is suggested on many of the mailing list troubelshooting messages.

4.  Finally, run Bjam to build your application.  On the Boost homepage it says you can run “make install”, but I found whenever I did this the build process would fail to compile any of the libraries.  I explicity invoked the Bjam tool as follows:

bjam toolset=sun stdlib=sun-stlport instruction-set=v9 address-model=64 install

This command may be redundant based on the parameters in user-config.jam, but I just wanted to be sure.  I turned off the monitor and went to bed because it takes a long time to build software on a Sun Blade 100!  Before leaving for work the next morning I checked a log file that I dumbed all of the build process output to and this time I had no errors.  The libraries were put in /opt/lib and my headers in /opt/include.  All is well that ends well.  Now it is time to put Sun’s compiler and tools to work!

Follow

Get every new post delivered to your Inbox.