This page discusses about some topics from the
TLM 2.0 getting started 4 example from Doulos.
-
Recently I started to study the TLM 2.0. After
going the presentations from the release, watching
the videos from Accellera, I started to go over
some code examples.
-
The first examples were the ones from the release.
Than I found some very good examples from Doulos. For
each one I created a makefile and run the example.
-
In the example,
tlm2_getting_started_4,
I had a small piece of code, that took me quite a long
time to digest. This was the code, which handles
memory management.
-
Before diving into this memory management
code, I'll explain its makefile. It supports
compilation, link and execute generation, regular
run and debug using GDB:
make run.o make run.x
make run.exe make DBG_OPT="gdb " run.exe
-
One thing, that is usually missing
from systemc
designs, is memory free of dynamic allocation.
The
C++ operator new is used, but its counterpart
delete,
is not.
If the program ends normally, the OS will
probably do the memory free.
Follows is a discussion on memory management, when
using TLM (Loosely Timed, Approximately Timed
models). It discuss how to reduce the number
of
usage of the new operator (allocate memory on the
heap). Delete is not used and not discussed.
-
For the memory management part, first is the
motivation
for using one. Using heap allocation
and heap free (delete) is highly recommended
to avoid. This has a significant
performance cost.
There is an example in the web, which
uses static array for its memory management.
While a static array simplifies the implementation,
it lacks the ability to cope with different rates peak
of memory multiple allocations with no free. A dynamic memory
management can easily absorb any multiple consecutive
allocation requests without a memory free.
-
The user has to implement two functions for the
memory management: allocate and free. In the example
a pointer based FIFO is used.
A pointer "free list" points to
a freed pre-allocated
transaction. If used, new allocation on the heap,
is saved.
Another arbitrary pointer, namely empties,
is used to hold a temporary data.
-
On a one to one rate, the mechanism is simple. First allocation uses
C++ new operator.
When it gets free, on the first time, empties is created and
later gets
copied to the free list. The next and previous
pointers, of the free list, are
kept as nulls.
-
Allocate copies free list next to free list.
So if there are consecutive
allocations, without a free transaction, the new
operator will be used
and more memory will be allocated. On the last
transaction re-use, the free
list next (null because it is the last one) is
copied to free list.
-
Now suppose there were three allocations,
which used new operator.
When multiple releases arrive
than:
1. Free list is populated and free list next is null,
2. Free list next free list is populated,
3. Free list next, next free list is populated,
or
fnn 0 0 1
fn 0 1 1
f 1 1 1
Part of the allocate / free code is listed
below. The rest is zipped in the following
makefile and C++ code (with minor changes)
mm::gp_t* mm::allocate()
{
gp_t* ptr;
if (free_list)
{
ptr = free_list->trans;
empties = free_list;
free_list = free_list->next;
}
else
{
ptr = new gp_t(this);
}
return ptr;
}
void mm::free(gp_t* trans)
{
//trans is free, save it in a free list
if (!empties)
{
empties = new access;
empties->next = free_list;
empties->prev = 0;
if (free_list)
free_list->prev = empties; //empties->next->prev = empties
}
free_list = empties;
free_list->trans = trans;
empties = free_list->prev;
}
|