|
A CSIM storage is a
resource which can be partially allocated
to a requesting process. A storage consists
of a counter (to indicate the amount of
available storage) and a queue for processes
waiting to receive their requested allocation.
A storage set is an array of these basic
storages.
A storage can be designated
to be synchronous. In a synchronous storage,
each allocate is delayed until the onset
of the next clock cycle.
Usage and queueing statistics
are automatically maintained for each
storage unit. These are "printed"
whenever a report
or a report_storages
statement is executed (see
section 19.2, "CSIM Report Output"
for details about the reports that are
generated).
A pointer to a dynamic
storage object is as follows:
Dynamic
Example: storage
*sd;
Before a storage can
be used, the constructor must be invoked:
Prototype:
storage::storage(char
*name, long size)
Static Example:
storage ss("mem",
1000);
Dynamic Example:
sd = new storage("mem",
1000);
A newly created storage
is created with all of the "storage"
available. Storages should be declared
with global variables in the sim (main)
process, prior to the beginning of the
simulation part of the model. A dynamic
storage must be initialized via the new
storage statement before it can
be used in any other statement.
The elements of a storage
can be allocated to a requesting process.
Prototype:
void storage::allocate(long amount)
Dynamic Example:
sd->allocate(10);
The amount of storage
requested is compared with the amount
of storage available at sd.
If the amount of available storage is
sufficient, the amount available is decreased
by the requested amount and the requesting
process continues. If the amount of available
storage is not sufficient, the requesting
process is suspended. When some of the
storage elements are deallocated by some
other process, the highest priority waiting
processes are automatically allocated
their requested storage amounts (as they
can be accommodated), and they are allowed
to continue. The list of waiting processes
is searched in priority order until a
request cannot be satisfied. In order
to preserve priority order, a new request
which would fit but which would get in
front of higher priority waiting requests
will be queued.
Note:
the alloc
method is equivalent to allocate:
Prototype:
void storage::alloc(long
amount)
Dynamic Example:
sd->alloc(10);
To return storage elements
to a storage, the deallocate procedure
is used.
Prototype:
void storage::deallocate(long
amount)
Dynamic Example:
sd->deallocate(10);
If there are processes
waiting, the highest priority processes
that are waiting are examined. Those that
will now fit have their requests satisfied
and are allowed to continue. Executing
a deallocate statement causes no simulated
time to pass.
Caution:
There is no check to insure that a process
returns only the amount of storage that
it had been previously allocated.
Note:
the dealloc
method is equivalent to the deallocate
method:
Prototype:
void storage::dealloc(long
amount)
Dynamic Example:
sd->dealloc(10);
Reports for storages
are most often produced by calling the
report function, which reports for all
CSIM objects. Reports can be produced
for all existing storages by calling the
report_storages
function. The report for a storage, as
illustrated below, gives the name of the
storage, the size (initial amount), the
average allocation request, the utilization,
the average time each request is "in"
the storage, the average queue length,
the average response time and the number
of completed requests.
| STORAGE
SUMMARY |
|
storage
name
|
size |
alloc amount |
alloc count |
dealloc amount |
dealloc count |
util
|
in-que length |
in-queue time
|
| store |
120 |
33.6 |
100335 |
30.0 |
100333 |
0.751 |
7.94470 |
7.91818 |
In some cases,
it is necessary to reset the statistics
counters for a specific storage unit.
Prototype:
void storage::reset(void)
Example:
s->reset();
Executing this
statement does not affect the state of
the storage. The "reset" and
the reset_storages statements each call
the storage::reset () statement for all
storage units in the model.
A storage set
is an array of storages. Each element
of the array is an individual storage.
Dynamic Example:
storage set *d_set
A storage set
must be constructed before the elements
of the set can be used.
Prototype:
void storage_set::storage_set(char
*name,long amount, long number_in_set);
Static
Example:
storage_set
s_set("set", 100, 5);
Dynamic
Example:
d_set =
new storage_set("set",
100, 5);
The example initializes
a set of five storages, each with 100
elements of storage available at the onset
of operation. The name is the name of
the set. Each individual unit of storage
is given a unique (indexed) name. In the
example, the first storage in the set
is named "set[0]", the second
is named "set[1]", and so on.
The last storage is named "set[99]".
Similarly, the individual units of storage
are accessed as elements of an array.
All of the operations which apply to a
storage also apply to the individual units
of a storage set.
Accessing individual
elements of a storage set are accessed
as shown in these examples:
Static Example:
s.set[i].allocate(10);
Dynamic
Example:
(*sd)[i])allocate(10);
Sometimes, processes
cannot wait indefinitely to allocate the
needed amount of storage. If such a process
executes the timed_allocate function,
then, if the requested amount of storage
is not available, the process will be
suspended until either the requested amount
of storage becomes available or the time-out
interval expires.
Prototype:
long storage::timed_allocate(long
amount, double timeout)
Dynamic
Example:
result =
sd->timed_allocate(10,100.0);
if(result ! = TIMED_OUT) . . .
The process must
check the function value (result) to determine
whether or not the requested storage was
obtained. If the value TIME_OUT is returned,
the process did not obtain any of the
requested storage. If this value is not
returned (EVENT_OCCURRED will in fact
be returned), then the process did obtain
the requested storage.
A storage unit
can be designated to be a synchronous
storage unit.
Prototype:
void storage::synchronous(double.phase,
double period)
Dynamic
Example:
s->synchronous(0.0,
1.0);
A synchronous
storage unit is similar to a normal storage
unit except that allocation requests are
always delayed until the beginning of
the next clock cycle. The clock phase
specifies the interval before the onset
of the first clock cycle, and the period
specifies the interval between successive
clock cycles.
To increase the
amount of storage (the number of storage
elements) in a storage:
Prototype:
void storage::add_store(long
amount)
Dynamic
Example:
sd->add_store(100);
Note:
The add method does not check the queue
of waiting processes to see if a process
could allocate some storage after some
storage is added.
To decrease the
amount of storage (the number of storage
elements) in a storage:
Prototype:
void storage::remove_store(long
amount)
Dynamic
Example:
sd->remove_store(100);
The name of a
storage can be changed at any time, as
follows:
Prototype:
void storage::set_name(char
*new_name)
Dynamic
Example:
sd->set_name("cache");
Only the first
ten characters of the storage's name are
stored.
5.11. Deleting Storage
or a Storage Set
To delete a dynamic
storage:
Example:
delete s;
To delete a dynamic
storage set:
Example:
delete s_set
Deleting a storage
or storage set is an extreme action and
should be done only when necessary.
These functions
each return a statistic which describes
some aspect of the usage of the specified
storage.
| Prototype: |
Functional
Value: |
| char
*storage::name() |
pointer
to name of store |
| long
storage::capacity() |
number
of storages defined for store |
| long
storage::avail() |
number
of storages currently available at
store |
| long
storage::qlength() |
number
of processes currently waiting at
store |
| double
storage::request_amt() |
sum
of requested amounts from store |
| long
storage::number_amt() |
time-weighted
sum of requesters for store |
| double
storage::busy_amt() |
busy
time-weighted sum of amounts for store |
| double
storage::waiting_amt() |
waiting
time weighted sum of amounts
for store |
| long
storage::request_cnt() |
total
number of requests for store |
| long
storage::release_cnt() |
total
number of completed requests for store |
| long
storage::queue_cnt() |
number
of queued requests at store |
| double
storage::time() |
time at store that is spanned by report |
Prototype:
void status_storages(void)
Example:
status_storages();
The report will
be written to the default output location
or to that specified by set_output_file
(see section
21.6, "Output File Selection").
Next
Section
|