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.
- Our toolchain supports C89, C99, inline or standalone assembly, and the
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.
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.
Apart from the standard libc, libm, POSIX, and libpthread headers, we provide a
few headers for accessing Rigel-specific constructs from C.
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.