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 storage is declared in a CSIM program
using the built-in type STORE.
Example:
STORE s;
Before a storage can be used, it must
be initialized by calling the storage
function.
Prototype:
STORE storage(char*
name, long size)
Example:
s = storage("memory",
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 storage must be
initialized via the 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 alloc(STORE
s, long amount)
Example:
alloc(s, 10);
The amount of storage requested is compared
with the amount of storage available
at s. 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.
Earlier versions of CSIM used an alternative
statement to accomplish this function:
Prototype:
void allocate(long
amount, STORE s)
Example:
allocate(10,
s);
Caution:
The order of the arguments for the allocate
statement (and the deallocate statement
too) can be confusing. Think of "allocating
n
elements of storage from storage s".
The alternative form is included to
accommodate legacy models.
To return storage elements to a storage,
the deallocate procedure is used.
Prototype:
void dealloc(STORE
s, long amount)
Example:
dealloc(s,
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.
An alternative form of the dealloc statement
is provided:
Prototype:
void deallocate(long
amount, STORE s)
Example:
deallocate(s, 10);
The alternative form is included to
accommodate legacy models.
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, summarizes usage
of and queueing for the storage units.
In some cases, it is necessary to reset
the statistics counters for a specific
storage unit.
Prototype:
void reset_storage(STORE
s)
Example:
reset_storage(s);
Executing this statement does not affect
the state of the storage. The "reset"
and the reset_storages statements each
call reset_storage() for all storage
units in the model.
A storage set is an array of storages.
Each element of the array is an individual
storage.
Example:
STORE *s_set; char *name[5];
A storage set must be initialized before
the elements of the set can be used.
Prototype:
void storage_set(
STORE* s_set. char
*name, long amount, long number_in_set);
Example:
storage_set(s_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.
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 timed_alloc(STORE
s, long amount,
double timeout)
Example:
result
= timed_alloc(s, 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.
An alternative form of the timed_alloc
statement is provided:
Prototype:
void timed_allocatelong
amount, STORE s,
double timeout)
Example:
result
= timed_allocate(s, 10, 100.0);
The alternative form is included to
accommodate legacy models.
A storage unit can be designated to
be a synchronous storage unit.
Prototype:
void synchronous_storage(STORE
s,
double.phase,double period)
Example:
synchronous_storage(s,
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
unit,
Prototype:
void add_more_store(STORE
s, long amt)
Example:
add_more_store(s,
100);
Earlier versions of CSIM used an alternative
statement to add more storage to a storage
unit; the alternative form is included
to accommodate legacy models:
Prototype:
void add_store(long
amount, STORE s)
Example:
To decrease the amount of storage (the
number of storage elements):
Prototype:
void remove_store(STORE
s, long amt)
Example: remove_store(s,
100);
The name of a storage can be changed
at any time, as follows:
Prototype:
void set_name_storage(STORE
s, char
*new_name)
Example:
set_name_storage(s,
"cache");
Only the first ten characters of the
storage's name are stored.
To delete a storage:
Prototype:
void delete_storage(STORE
s)
Example:
delete_storage
s);
To delete a storage set:
Prototype:
void delete_storage_set(STORE
s_set[])
Example:
delete_storage(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(STORE
s) |
pointer to name
of store |
| long storage_capacity(STORE
s) |
number of storages
defined for
store |
| long avail
(STORE s) |
number of storages
currently
available at store |
| long storage_qlength(STORE
s) |
number of processes
currently
waiting at store |
| double storage_request_amt(STORE
s) |
sum of requested
amounts from
store |
| long storage_number_amt(STORE
s) |
time-weighted
sum of
requesters for store |
| double storage_busy_amt(STORE
s) |
busy time-weighted
sum of
amounts for store |
| double storage_waiting_amt(STORE
s) |
waiting time
weighted sum of
amounts for store |
| long storage_request_cnt(STORE
s) |
total number
of requests for store |
| long storage_release_cnt(STORE
s) |
total number
of completed
requests for store |
| long storage_queue_cnt(STORE
s) |
number of queued
requests at
store |
| double storage_time(STORE
s) |
time at store
that is spanned by
report |
Prototype:
void status_storages
(void)
Example:
status_storages
();