Home News People Research Study Search

Institute for Computing Systems Architecture

Computer Architecture Simulation & Visualisation

Rainbow separator

Hase++ Design documentation

Frédéric Mallet
2003-09-03
This document describes how the C++ source code for Hase++ is organised. I am not the designer of Hase++, I am just reporting the modifications I have made and the design issues I have understood.
Another report documents Hase++ primitives
. JavaHase design documentation

Location and versioning

All source files are located in /group/project/hase/Linux/Hase++/, which I will abbreviate into ${Hase++} for future references. To use Hase++ from a C++ program, the simkernel.h file, located in the ${Hase++} directory, must be included and the source files must be linked against the libsim3.a library file, located in the ${Hase++}/lib directory.

Recently, I have modified Hase++ quite a lot to enhance performance. Before doing these modifications, I have backed it up into ${Hase++}/old.
Several improvements have been applied, they can be decomposed into 2 families. Applying the 1st family improvements led to version 1 in ${Hase++}/v1 directory. On these improvements, a second family of improvements have been applied, leading to version 2 in ${Hase++}/v2 directory. The version 2 has not yet superseded version 1 since the improvements applied have not proved to make any difference at all on the actual performances.
The current Hase++ library being used is version 1. To swap from version 1 to version 2, enter the command make v2, all .h files will be copied from ${Hase++}/v1 to ${Hase++} and the right libsim3.a file will be used. To swap back to version 1, enter the command make v1.

Warning: Since Hase++ is not fully object-oriented and header files contain code, moving from one version to another may require recompiling dependent files like library files (e.g. libsync.a) or even HASE projects.

Future modifications should be applied to version 1, version 2 should be maintained to investigate further performance issues. According to results obtained with Simjava, introducing passive entities could be a way to get a huge improvement in performances.
Hase projects use header file from ${Hase++}. That means, modifications are not taken into account until the make v1 or make v2 commands have been entered. This protects all-the-day users from being disturbed by too many updates or inconsistent versions.

Modifications must not directly be applied to files contained in the ${Hase++} directory. Besides, not all files are present in this directory (e.g. no .c file).

General comments

Apparently, Hase++ has been designed from an existing discrete-event scheduler writtent in C. Later on, some classes have been built upon it to make it object-oriented. The gain from encapsulating it into classes is not obvious to me and leads to some confusion in finding the code to be modified. Most of the time, the behaviour is directly written into header files.
Most of the core functions are performed by the mgr.h and evqueue.h files (alleged original discrete-event manager). Most methods provided by surrounding classes just call functions defined in mgr.h. Most of the process-based primitives are written into the simkernel.h and call basic primitives of mgr. I did not know that when I started to modify Hase++ and some of the modifications I made use the object-oriented structure which may lead to more confusion.

Version 1

Major modifications applied

  1. The major improvements come from the memory usage optimisation applied thanks to valgrind 1.9.6. The SIM_PUT macro has been modified to use the new construct. The send methods are generated differently to recover the memory. The SIM_CAST_DEL macro has been introduced in addition to the SIM_CAST macro in order to recover the memory when required.
  2. The generated send method uses the colour field to determine whether or not the event is dumped into the trace file. Consequently, the SIM_PUT macro becomes obsolete since it was only used when calling sim_schedule directly.
  3. sim_get_next with predicate has been optimised. Previously, the entity would wake up when any kind of event was received. This entity would go back to wait if the predicate did not match. With the optimisation, the entity is only woken up when the expected predicate matches the incoming event. This reduces the number of context switches.
  4. Hase++ was using a QT timer to compute the time to run a simulation. Hence, Hase++ had to be linked against the QT library and was dependent on QT. Now, Hase++ is using the system library sys/time.h and is not dependent on QT any longer.
  5. A sim_get_next_before primitive with predicate has been defined.
  6. The sim_or predicate has been defined.
  7. Some unnecessary intermediate method calls have been removed.

Files for Hase++ version 1

Makefile
compiles all files and generates the libsim3.a file. No modification is taken into account until the make v1 command has been entered from the ${Hase++} directory.
entity.h
entity
An entity has a state, some ports and is attached to a thread. Most of its behaviour, apart from the port management, is delegated to a global mgr instance (named S).
evqueue.h
evqueue, qstats
Represent a queue of events. Both the future and deferred queues (cf. mgr.h are instances of the evqueue class. Some statistics about the queues (e.g. max length, number of accesses) are maintained in the qstats structure.
kernel.h
Includes some header files. Used by simkernel.c, sim_system.c, sim_port.c, sim_entity.c and entity.h.
mgr_i.h
mgr_i
Abstract Event Manager. Fully abstract class that defines core services. An Event Manager knows a list of sim_entity and has 2 queues, one future and one deferred queue. When an event is scheduled, it is pushed into the future queue. When the simulation time of this event is reached the event is popped out of the future queue and processed. In case it is a send event and the receiving entity is not available or not waiting for any event, the event is pushed into the deferred queue until the entity becomes available and requires an event occurrence (e.g. by calling sim_waiting). When all deferred events are processed, the simulation time increases and associated future events are processed. When there is no remaining future event, the simulation stops.
mgr.h
mgr::mgr_i
Concrete Event Manager. Implements services defined by mgr_i.h.
mgr.c
Only defines the entity_thread function. The thread library used (pthread), calls a function (entity_thread) when a thread should be started. The thread library cannot directly call a method.
predicate.h
Only declares the SIM_ANY and SIM_NONE predicates. Must be maintained to avoid 'multiple declaration' of SIM_ANY and SIM_NONE. It is only included from simkernel.c while simkernel.h is included from every header file for every entity.
random.c
TRandomNumberGenerator
Provides a class to generate pseudo random numbers.
semaphore.h
Mutex, semaphore_i, semaphore
Basic classes used by mgr to guarantee mutual exclusion of some critical code sections. This mechanism is required when using threads because no construction is provided by the language.
sim_entity.h
Empty. The sim_entity class is declared in simkernel.h.
sim_entity.c
sim_entity
Wrapper around entity. Was mainly used to filter traces and add a verbose mode (auto_trace). Now, defines some higher level primitives (sim_waiting, sim_get_next_before).
sim_event.h
A sim_event is emitted by an entity with a tag and a time. It may have data. It should, but may not, be sent through a sim_port, in which case the property src_port identifies this port.
sim_event.c
sim_event
Defines methods declared in sim_event.h.
sim_nt.h
I think this file can be removed. In that case, Hase (Project.c) must be modified so the main .h file is generated without the instruction #include <sim_nt.h> when a project is built.
sim_port.h
A sim_port has a name and is attached to an entity using sim_entity::join_port. Later on, a sim_port can be linked to a destination entity (using link_ports).
sim_port.c
sim_port
Defines methods declared in sim_port.h
sim_predicate.h
sim_predicate
Declares the abstract class sim_predicate, base of every predicate.
sim_system.h
Empty. The sim_system class is declared in simkernel.h.
sim_system.c
sim_system
Wrapper around mgr. When using Hase++, one should define an instance of sim_system. This instance allows for adding entities, linking ports, running the simulation, accessing entities by name.
When a simulation is generated by Hase, this instance is named sim.
sim_types.h
Defines the sim_time and sim_entity_id subtypes.
simkernel.h
sim_any_p, sim_or, sim_none_p, sim_from_p, sim_type_p, sim_from_port
Declares several classes to wrap functions defined in mgr.h. Defines some macros (SIM_PUT, SIM_CAST, SIM_CAST_DEL). This is the main file to include when using Hase++ (instead of simpp.h).
simkernel.c
Few methods declared but not defined in simkernel.h are defined here.
simpp.h
Can be removed, simkernel.h can be used directly instead. If removed, HASE (Project.c) must be updated (see sim_nt.h).
threads.h
thread_i, h_thread::thread_i
Wrapper around a sim_entity and a p_thread. p_thread is a class to handle threads provided by the system.
threads.c
Almost empty. Just here so a threads.o file is generated by the Makefile.

Version 2

Version 2 tries to enhance performances by working on the data structure to represent queues of events. It intends to reduce:
  1. the time to allocate new events, by having large bunches of pre-allocated events. A flag identifies events in use ;
  2. the time to remove, add or extract events by using a double-end queue instead of an array.

No gain in performances was obtained because apparently neither the future nor the deferred queues get very big. Even with simulations involving million of events (e.g. Xyratex) the maximum size of queues remains under 200 events.

The only modification consists in replacing evqueue.h by Evqueue.hh and Evqueue.cpp. This implies some minor modifications in mgr.h because the allocation of events is slighly different.

Distribution of Hase++

The 'public' version of Hase++ is located in /group/project/Hase/public/Hase++. Currently, there is no automatic or versioning mechanism to update this release. I just use the Unix cp command to update Hase++ when required.
However, entering make archive command from /group/project/Hase/public will produce the hase2_src.tar.Z archive file that contains Hase++ along with Hase and JavaHase.

RedHat 9

The DICE systems currently under RedHat 7 is going to move to RedHat 9. The RedHat 9 has a different version of C++ compiler (gcc 3.2.2). This compiler is ISO compliant and did not accept the Hase++ code as it was. The Hase++ source code is now compatible with both gcc 2.96 and gcc 3, but the library files are not.
libsim3.a and libsim3b.a have been compiled with gcc 2.96.
libsim9.a and libsim9b.a have been compiled with gcc 3.2.2.
When definitively moving to RedHat 9, one can either rename all libsim9* to libsim3* or change the way the Makefile is generated by Hase to include -lsim9 instead of -lsim3 (see Project.c).

Return to Documents about HASE & SimJava


Rainbow separator

HASE Project
Institute for Computing Systems Architecture, School of Informatics, University of Edinburgh


Home : Research : Groups : Hase : Manuals : Design 

Please contact our webadmin with any comments or changes.
Unless explicitly stated otherwise, all material is copyright © The University of Edinburgh.