
Computer Architecture Simulation & Visualisation
Hase++ 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
- 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.
- 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.
- 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.
- 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.
- A sim_get_next_before primitive with predicate has been defined.
- The sim_or predicate has been defined.
- 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:
- the time to allocate new events, by having large bunches of pre-allocated events. A flag identifies events
in use ;
- 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
HASE Project
Institute for Computing Systems Architecture, School of Informatics,
University of Edinburgh
Please contact our
webadmin with any comments or changes.
Unless explicitly stated otherwise, all material is
copyright © The University of Edinburgh.