Tourmaline: Multifacet's Transactional Memory Functional Simulator, released as part of GEMS 1.2 on 11 February 2006.
Overview
The Tourmaline module is used to rapidly execute transaction memory programs (using Simics "magic" instructions) correctly, though without cache timing information of any sort. Tourmaline preserves transactional semantics to allow quick development of transactional software and workloads, without incurring the overhead of detailed timing simulation. It is a module separate from Ruby and Opal, that may be loaded to enable transactional memory programs to be run within Simics at near-Simics execution speeds when using the Serializer controller, and at improved (vs. Ruby) speeds when using more sophisticated controllers.
The heart of Tourmaline consists of a Transaction Controller, inherited from base class TransactionController. The GEMS 1.2 release of Tourmaline includes two built-in controllers, Serializer and Generic, which are described below in the section entitled "Transaction Controllers".
Tourmaline emulates the same binary interface as the ["Transactional Memory"] implementation in Ruby. However, Tourmaline is intended to run stand-alone, without either Ruby or Opal loaded. It will not function correctly in the presense of these modules.
Detailed documentation can be found in the $GEMS/tourmaline/ directory of the GEMS 1.2 Release, in the README.tourmaline file. Note that Tourmaline was developed for Simics 2.2.X, and is not tested for Simics 2.0.X. Simics 3.0.X compatibility is available but experimental.
Transaction Controllers
Built-in Controllers
The GEMS 1.2 release of Tourmaline includes two built-in controllers, Serializer and Generic:
Serializer is designed to operate as quickly as possible while still preserving transactional semantics. This controller operates by monitoring the transaction nesting depth of each processor. When a processor's transaction nesting depth transitions from zero (0) to one (1), Tourmaline disables all other processors (via the SIM_disable_processor() API call). Processors are re-enabled (via SIM_enable_processor()) when the transaction nesting level of the currently-enabled processor transitions from one (1) to zero (0). Thus, under Serializer, if processor P is executing a transaction, then P is the only active processor. Of course, transactional semantics are trivially satisfied when only a single processor is executing instructions.
Generic attempts to functionally emulate a realistic, if simple, implementation of hardware transactional memory. Unlike Serializer, it allows more than one processor to execute transactions concurrently. When a processor is executing a transaction, Generic tracks the read- and write-set of each transaction (subsuming nested transactions), allowing memory requests to complete normally. Generic logs transactionally-overwritten values, to allow memory writes to be un-done at abort-time.
- On transaction commit, the read-sets, write-sets, and log of previous values are discarded.
- On transaction abort, the previous values of memory are atomically restored.
More information on Serializer and Generic may be found in its source code documentation and in the Tourmaline readme file.
Transaction Controller Cookbook
Tourmaline's TransactionController class is easily extended to make new Transaction Controller types. Below is a step-by-step guild on how to create new Transaction Controllers.:
Copy Skeleton.h and Skeleton.C to new files in $GEMS/tourmaline/transcon/ These will become the header and source files for the new transaction controller. Be sure to change the C++ class name in the new files. In this example, we use MyController as the name for our new transaction controller.
cd $GEMS/tourmaline/transcon/ cp Skeleton.C MyController.C cp Skeleton.h MyController.h [ edit MyController.C and MyController.h and change the class name ]
Edit TransactionControllerTypes.h, and add the following:
A Transaction_Controller_MyController, entry to the TransactionControllerType enum.
1 // Each transactional controller should have an enum entry here 2 enum TransactionControllerType { 3 Transaction_Controller_Serializer = 0, 4 Transaction_Controller_Generic, 5 Transaction_Controller_MyController, 6 Transaction_Controller_COUNT /* Leave this in */ 7 };
- A one-word name for your controller to the names array--this name will correspond to the value used in the configuration file:
1 // Each transactional controller should have a name here 2 const char * const TransactionControllerNames[] = { 3 "Serializer", 4 "Generic", 5 "MyController", 6 "INVALID_CONTROLLER" 7 };
- A description of the controller in the description array.
1 // usable for help messages 2 const char * const TransactionControllerDescriptions[] = { 3 "Serializer: [description]\n", 4 "Generic: [description]\n", 5 "MyController: A shiny new TransactionController\n", 6 "INVALID_CONTROLLER: [warning message]\n" 7 };
Edit TransactionControl.C, specifically the allocateTransactionController() function, and add a case statement for your transaction controller.
1 case Transaction_Controller_Generic: 2 t = new GenericController(); 3 break; 4 case Transaction_Controller_MyController: 5 t = new MyController(); 6 break;
Add your MyController.C file to the Makefile's SRC_CPP list.
SRC_CPP := \ initvar.C \ ... GenericController.C \ MyController.C
Before making your own module, it is highly recommended that you read the README.tourmaline file in its entirety.
Compilation of Tourmaline
Tourmaline's compile syntax is very similar to that of Ruby and Opal. A required argument to "make" is the DESTINATION= definition, which determines where the Tourmaline module will be installed. Otherwise, compilation is identical to other modules.
NOTE: Tourmaline was developed and tested with Simics 2.2.X. It is not compatible with Simics 3.0.
Typically, compilation is performed via:
make [-j <int>] DESTINATION=<DEST_NAME>
eg.
make -j 4 DESTINATION=TMTest
You must make the following changes in your $GEMS/simics/src/extensions directory to use Tourmaline:
cd $GEMS/simics/src/extensions/ mkdir tourmaline cd tourmaline ln -s ../../../../tourmaline/simics/commands.h ln -s ../../../../tourmaline/module/commands.py ln -s ../../../../tourmaline/module/Makefile ln -s ../../../../tourmaline/module/tourmaline.c
You must also add the following line to file $GEMS/simics/config/modules.list-local:
tourmaline | API_2.0 | v9
NOTE: Simics may not detect that its list of modules has changed, so it may be required to delete the modules.cache file in $GEMS/simics/[HOST_TYPE]/lib/ if compilation of Tourmaline fails when linking the Tourmaline module. This problem is characterized by the error message:
No rule to make target: tourmaline
Loading the Tourmaline Module
Loading and Running
Once Tourmaline is compiled, it can be loaded just as any other Simics module. Simics must be invoked with the -stall option when using any Transaction Controller that uses the memory timing interface, such as Generic. It is strongly recommended that the user also enable Simics "magic" breakpoints before loading Tourmaline. A configuration should also be loaded before loading Tourmaline. A typical invocation may look something like this:
host% cd $GEMS/simics/home/TMTest host% ./simics -stall simics> read-configuration [path to a valid simics checkpoint] simics> magic-break-enable simics> istc-disable simics> dstc-disable simics> load-module tourmaline Successful installation of the Tourmaline TM-Acceleration module.
Before beginning execution, the init function must be invoked:
simics> tourmaline0.init Initializing Tourmaline Module ------------------------------ Initializing TourmalineConfig... Done. Creating Transaction Controller: Controller_type: Serializer number_of_procs: 4 Creating Profiler... Done. Tourmaline Module Initialized. Tourmaline Configuration ------------------ simics_version: simics-2.2.19 compiled_at: 12:58:53, Feb 1 1985 hostname: myhost.mydomain.com g_RANDOM_SEED: 1 SPECIFIED_TRANSACTION_CONTROLLER: Serializer g_NUMBER_OF_PROCESSORS: 4 g_NUMBER_OF_ALLOWED_ABORTS: 10 g_SERIALIZATION_WARNING_ENABLE: true g_PRINT_XACT_STATUS: false g_SERIALIZER_N_TRANSACTIONS: 100
Simulation may now be started by passing the command c to Simics.
Supported Commands
Tourmaline currently supports the following commands:
clear-stats: Zeroes statistics gathered by Tourmaline's profiler.
dump-stats [filename]: Dumps the statistics gathered by Tourmaline's profiler. If a parameter (a filename) is given, the statistics are dumped to a file. Otherwise, statistics are dumped to stdout.
init: Initializes the Tourmaline module.
setparam and setparam_str: Used to overwrite default configuration values. Must be invoked after loading Tourmaline, but before invoking tourmaline0.init.
Configuration Options
The following parameters have default values set at compile-time from values in $GEMS/tourmaline/config/tourmaline.defaults. These parameters may be overwritten at runtime by invoking the setparam and setparam_str commands (see above) before tourmaline0.init.
g_RANDOM_SEED: Determines the random seed used by Tourmaline. If this parameter is set to zero, the random seed is generated from the return value of time().
g_NUMBER_OF_PROCESSORS: Can be used to statically set the number of processors in the simulation. Setting this variable to zero allows Tourmaline to automatically determine the number of processors (recommended).
SPECIFIED_TRANSACTION_CONTROLLER: A string that specifies which of the available transaction controllers should be used. Options: Serializer, Generic
g_NUMBER_OF_ALLOWED_ABORTS: An integer that determines how many times a transaction should be tried before resorting to serialization for livelock-avoidance. Used only by the Generic Transaction Controller.
g_SERIALIZATION_WARNING_ENABLE: If enabled, prints a warning to the console every time serialization is used to ensure transactional success. NOT recommended for the Serializer controller.
g_PRINT_XACT_STATUS: If enabled, a "console" of transaction status will be displayed when running. Obscures normal output--NOT recommended if output if directed to a file.
g_SERIALIZER_N_TRANSACTIONS: When set to a positive value, the Serializer transaction controller will run g_SERIALIZER_N_TRANSACTIONS transactions, then break the simulation using SIM_break_simulation. After the break, exactly zero processors are executing code inside a transactions. Only the Serializer transaction controller respects this value.