Example

Here is an annotated sample program written for Rigel in C99. It contains a parallel implementation of Conway's Game of Life using the Rigel Task Model and several Rigel-specific functions and idioms.

Language

  • Our toolchain supports C89, C99, inline or standalone assembly, and the Blocks extension. Clang itself also supports C++03 and much of C++11, but ports of the C++ standard and runtime libraries are still in progress.
  • The language features supported are listed here.
  • Language extensions supported are listed here.

Macros

We define a few preprocessor macros to help C-like code detect when it is being compiled for Rigel. Chief among these is __RIGEL__, which should be #defined to 1 when compiling for Rigel. To see a complete list, run:

$RIGEL_INSTALL/host/bin/clang -ccc-host-triple rigel-unknown-unknown -dM -E - </dev/null.

Headers

Apart from the standard libc, libm, POSIX, and libpthread headers, we provide a few headers for accessing Rigel-specific constructs from C.

rigel.h

rigel.h has inline assembly implementations of cycle-accurate timers, simulation control, special Rigel instructions, system topology queries, and system calls to get high-quality random numbers from the host:

  • RigelGetThreadNum(), RigelGetCoreNum(), RigelGetClusterNum(): Get the 0-based chip-wide thread, core, or cluster identifier of the requesting thread.
  • RigelGetNumThreads(), RigelGetNumCores(), RigelGetNumClusters(): Get the total number of threads, cores, or clusters in the system being simulated.
  • RigelGetCycle(): Get the current cycle number, starting from 0 at target system boot (the beginning of the simulation)
  • SIM_SLEEP_ON(), SIM_SLEEP_OFF(): In the simulator, all threads except 0 start asleep to make initialization go faster. Running cores can call SIM_SLEEP_ON() and SIM_SLEEP_OFF() to sleep or wake all other threads in the system, respectively.
  • StartTimer(int), StopTimer(int), ClearTimer(int): The simulator keeps an array of 64k cycle-accurate timers for the target to use. These three functions will start, stop, or set to 0 the timer with the given index. These timers are used pervasively in our benchmarks to time the parallel section of the benchmark or to give more fine-grained timing information on interesting pieces of code.
  • RigelSRand(int, int): The simulator also maintains a dedicated uniform RNG for the target to use when fast random number generation is desired (for example, when estimating the performance of a design with a per-core LFSR-based RNG). This function is used to seed that RNG with 64 bits of state (2 32-bit ints).
  • RigelRandInt(), RigelRandUInt(), RigelRandFloat(): These functions are used to get a random int, unsigned int, or float between specified minimum and maximum values from the simulator's RNG.