Anexo
A1. Funciones para control y reporte de tiempo:
sc_stop()
Para
la simulación y causa el sc_start() para retornar el control a la rutina del sc_main().
sc_time_stamp()
Retorna
un objecto sc_time con el
tiempo actual de la simulación.
sc_simulation_time()
Retorna
un valor de tipo double con el tiempo actual d ela simulacion la unidad actual
del tiempo de defecto. Volver
A2. Pasos Del Planificador.
1.- Fase De la Inicialización. Cada proceso del método se ejecuta una vez
durante la inicialización y se ejecuta cada proceso hilo es ejecutado hasta que
se encuentra una declaración de la espera.
El orden de la
ejecución de procesos es sin
especificar. El orden de la ejecución
entre los procesos es determinista. Esto
significa que dos funcionamientos de simulación que usan la misma versión del
mismo simulador deben rendir resultados idénticos. Sin embargo, diversas versiones o un diverso
simulador pueden rendir un diverso resultado si el cuidado no se toma al
escribir modelos.
2.- Fase de
Evaluación (Evaluate Phase). Del conjuntos de los procesos
que están listos para funcionar
(correr), seleccionar un proceso y reanudar su ejecución. El
orden en la cual los procesos se seleccionan para la ejecución del
sistema de los procesos que están
listos para funcionar está sin
especificar.
La ejecución de un proceso puede incluir llamadas a la
función del request_update() la cual programa
las llamadas pendientes a la función update() en la
fase de la actualización. La función del
request_update() se puede llamar solamente dentro de funciones del miembro
de un canal primitivo.
3) repite el paso 2
para cualquier otro proceso que sea listo funcionar.
4) Fase De la
Actualización. Ejecute cualquier llamada
pendiente al update() de llamadas a la función del request_update()
ejecutada en la fase de la evaluación.
5) Si notificaciones
pendientes, se determina qué procesos son listos funcionar e ir al paso 2.
6) Si no hay mas notificaciones para tiempo posteriores (timed
notification)
se acaba la simulación.
7) Sino, avance el tiempo actual de la simulación hasta que finalice la notificación
sincronizada del acontecimiento.
8) Se determina qué procesos llegan a estar listos funcionar
debido a los acontecimientos que tienen notificaciones pendientes en el tiempo
actual. Vaya al paso 2. Volver
A3. Tipos de datos en SystemC
Este
tipo son enteros de precision fija con y sin signo.
Son representados como un arreglo de bits.
sc_int<length> variable_name, variable_name,
...;
sc_uint<length> variable_name, variable_name,
...;
Estos
tipos se utilizan para las operaciones aritméticas y lógicas en enteros sin
signo y con signos y menor que o igual a 64 bits. Todas las operaciones se realizan con 64 bits
de precisión y después se convierten al tamaño apropiado con el
truncamiento. Una representación del
complemento de dos se utiliza para los enteros con signo. El uso de estos tipos de datos será menos
eficiente que el uso de los tipos de datos incorporados de C.
Ejemplo
sc_int<5> a; // a is a 5-bit signed integer
a = 13; // a gets 01101, a[4] = 0, a[3] = 1, ..., a[0]
= 1
bool b;
b = a[4]; // b gets 0
b = a[3]; // b gets 1
c = a.range(3, 1); // c gets 110 - interpreted as -2
Estos
tipos son enteros sin signo firmados y arbitrarios de
la precisión. Se representan como
arreglo de bits.
sc_bigint<length> variable_name, variable_name,
...;
sc_biguint<length> variable_name , variable_name, ...;
Estos
tipos se utilizan para las operaciones aritméticas en los enteros sin signo
firmados y mayores que o igualan a 64 pedacitos. Una representación del dos-complemento se
utiliza para los enteros con signo.
Este
tipo representa la lógica 4-valued. El valor se interpreta como variable de un
solo bit, no como número. Es útil para modelar lógica de triple
estado. El uso de la lógica 4-valued será menos eficiente que el uso del
sintaxis de la lógica 2-state (sc_int,
sc_uint):
sc_logic variable_name, variable_name, . . . ;
Ejemplo
{
bool control, data;
sc_logic ts_out;
if (control == false) {
ts_out = 'Z'; // Set the drive to Z
}
else {
ts_out = data; // Set the drive to data
}
}
sc_lv<>
Este
tipo es un arreglo de bits de tipo sc_logic. El valor
es interpretado como un multi-bit
variable, no como un numero. Es normalmente usado para
el modelamiento de tri-state logic
sc_lv<length> variable_name, variable_name, ...
;
Ejemplo
sc_lv<38> a; // 38-bit bit vector
sc_lv<4> b;
sc_logic c;
b = "ZZZZ";
cout << "b = " << b.to_string();
// use to_string() method for readable character string
Los
modelos de un nivel más alto pueden utilizar números de punto flotante para
modelar operaciones aritméticas. Estos
números se convierten a menudo a los tipos de datos del punto fijo para la
puesta en práctica de hardware. Estos
tipos son precisión arbitraria y tienen argumentos estáticos.
sc_fixed<wl,
iwl, q_mode, o_mode, n_bits> object_name, object_name, ... ;
sc_ufixed<wl,
iwl, q_mode, o_mode, n_bits> object_name, object_name, ... ;
·
wl: total word length,
number of bits used in the type.
·
iwl: integer word length,
number of bits to the left of the binary point (.).
·
q_mode: quantization mode.
·
o_mode: overflow mode.
·
n_bits: number of
saturated bits, used for overflow mode.
Estos
tipos utilizan una precisión fija y tienen argumentos estáticas. La mantisa se limita a 53 bits. Son implementadas con valores de doble punto
flotante (double precision floating point). Utilizan los mismos nombres de parámetros,
argumentos y orden del tipos arbitrarios de precison de punto fijo:
sc_fixed_fast<wl, iwl, q_mode, o_mode, n_bits>
object_name, object_name, ... ;
sc_ufixed_fast<wl, iwl, q_mode, o_mode, n_bits>
object_name, object_name, ... ;
·
wl: total word length,
number of bits used in the type.
·
iwl: integer word length,
number of bits to the left of the binary point (.).
·
q_mode: quantization mode.
·
o_mode: overflow mode.
·
n_bits: number of
saturated bits, used for overflow mode.
Este tipo usa precision fija y
tiene argumentos estaticos. La mantisa esta limitada
a 53 bits.
sc_fixed_fast<wl, iwl, q_mode, o_mode, n_bits>
object_name, object_name, ... ;
sc_ufixed_fast<wl, iwl, q_mode, o_mode, n_bits>
object_name, object_name, ... ;
·
wl: total word length,
number of bits used in the type.
·
iwl: integer word length,
number of bits to the left of the binary point (.).
·
q_mode: quantization mode.
·
o_mode: overflow mode.
·
n_bits: number of
saturated bits, used for overflow mode.
Estos tipos son los mismo que sc_fix, sc_ufix, sc_fix_fast, sc_ufix_fast
respectivamente excepto los argumentos
son non-static.
sc_fix object_name (list of options) ;
sc_ufix object_name (list of options) ;
A4. Tipos de canales
sc_signal:
The sc_signal channel implements the
sc_signal_inout_if interface. Los canales
sc_signal son
referidos a menudo como señales.
Se utilizan para describir señales del hardware. Se utiliza tanto para comunicaciones punto a
punto o multipunto. Las señales
implementan la semántica evaluate-update
para evitar dependencias de la orden de los datos. La señal mantiene un current_value,
un new_value y un old_value.
Durante la fase de la evaluación escribir en la señal
causara que el valor sea escrito en new_value. Sucesivo escrituras a la señal hará que el new_value
sea actualizado cada vez (el ultimo gana (last one wins)). Durante la fase de la actualización si el new_value es diferente de current_value
entonces el current_value se mueve al old_value y entonces el new_value
se mueve al current_value y un acontecimiento ocurre.
SC_MODULE (module_name) {
sc_signal<int> d ;
sc_signal<char> e ;
sc_signal<sc_int<10> > f;
// rest of module not shown
} ;
sc_buffer
Un
canal del sc_buffer se comporta exactamente como un
canal del sc_signal excepto que al
escribir el valor es siempre actualizado y ocurre un value_changed_event,
incluso cuando el new_value es igual al current_value.
sc_fifo: implementa las interfaces sc_fifo_in_if y sc_fifo_out_if. Un
canal sc_fifo
implementa una FIFO. Es una conexión
punto a punto y puede ser conectado solamente con un
entrada y un puerto de salida al conectar entre los módulos.
SC_MODULE (module_name) {
// channels
sc_fifo<int> d; // type int, depth of 16
sc_fifo<char> e ; // type char,depth of 16
sc_fifo<sc_int<10> > f; // type sc_int<10>, depth of 16
// rest of module
} ;
Cada proceso puede procurar trabar el sc_mutex. Una vez que el proceso trabe el canal
entonces tiene acceso al recurso compartido.
Este acceso no es forzado por el canal sino es simplemente parte de la
semántica del uso. Después de que el
canal se acabe con el recurso compartido abre el canal de modo que otros
procesos puedan tener acceso al recurso compartido. El canal advierte si las peticiones múltiples
se publican durante el mismo ciclo del delta.
Solamente el proceso que trabó el canal puede abrirlo. Si el canal entonces se traba la sensibilidad
dinámica se utiliza para suspender y un-para suspender (un-suspend)
un proceso de la petición.
El canal sc_semaphore implementa la interfaz sc_semaphore_if . Es similar al canal sc_mutex pero permite el acceso concurrente limitado. Se crea con un parámetro positivo obligatorio
del tipo int. El parámetro se asigna a
una variable interna de la "cuenta".
El parámetro representa el número máximo de "usuarios
concurrentes" del canal. La cuenta
interna se decrementa en cada wait() o trywait()
acertado. La cuenta interna se
incrementa en cada post(). El canal es tan largo disponible como cuenta
interna > 0.
A5. Definición de modulos
Estos son los 3 pasos para definir módulos
dentro otro módulo.
Paso1: Cree el caso del módulo
El módulo se crea como miembro de los datos del módulo del padre.
Sintaxis: module_name instance_name;
Paso 2: Inicialice el caso del módulo.
Inicialice los casos de módulos dentro de la lista de la inicialización del constructor del módulo del padre. La secuencia que usted proporciona como parte de la inicialización es el string_name del módulo. Se recomienda guardar el string_name igual que instance_name.
Paso 3: Unir los puertos.
Hay dos tipos de sintaxis para unir los puertos. El primero y preferido método está al lado de la conexión nombrada. El segundo está al lado de conexión posicional. El estilo nombrado de la conexión es el mapeo explícito. El unir se hace en el cuerpo del constructor del módulo.
Primera forma:
Sintaxis: instance_name.port_name(channel_or_port);
El estilo posicional de la conexión es el mapeo implicado.
Segunda Forma:
El primer port_or_channel en la lista mapea al primer puerto definido en el módulo. El segundo port_or_channel de la lista mapea al segundo puerto en el módulo, etcétera.
Sintaxis:
instance_name(channel_or_port, channel_or_port,
. . .);
A6.- Definición de módulos
dentro del sc_main( ).
Paso 1: Definición y iniciación de un modulo.
La definición del módulo es la creación de los objetos del módulo.
Sintaxis: module_name
instance_name ("string_name") ;
Paso 2: Unir los puertos.
Se hace al igual que en caso de modulo dentro de un modulo
Sintaxis:
instance_name.port_name(channel_or_port);
ó
module_name instance_name
("string_name") ; Volver
#include
"systemc.h"
#include
"adder.h"
#include
"stimgen.h"
#include
"monitor.h"
int sc_main(int
argc, char *argv[ ])
{
// Create
fifos with a depth of 10
sc_fifo<int>
s1(10);
sc_fifo<int>
s2(10);
sc_fifo<int>
s3(10);
// rest of
body not shown
return 0;
}
sc_time t1(20,SC_NS);
sc_time t2(10,SC_NS);
sc_clock clk2("clk2", t1, 0.5, t2, true);
// periodo de 20ns
// ciclo de trabajo de 50%
// Primer
canto a 10ns
// Si el primer canto es positivo
Nombre
Sintaxis |
Nombre |
Tipo |
period: |
Periodo
del reloj |
variable
del tipo sc_time |
|
|
Valor
por defecto: 1 de la unidad tiempo por defecto |
duty_cycle: |
Ciclo
de trabajo |
variable
tipo double |
|
|
Valor
por defecto: 0,5 |
start_time: |
tiempo
del primer |
variable
del tipo sc_time |
|
canto |
Valor por defecto: 0 |
positive_first: |
Primer
canto positivo |
Variale tipo Bool |
|
|
Valor
por defecto: true |
A.9 Ejemplo de implementación:
Se implementara una compuerta EXOR, usando 4 puertas
NAND.
El Codigo para una compuerta
NAND, es el siguiente:
# include
“systemc.h”
SC_MODULE
(nand2)
{
sc_in<bool> A, B;
sc_out<bool> F;
void do_nand2 ()
{
F.write (! A.read() &&B.read()
) );
}
SC_CTOR(nand2)
{
SC_METHOD(do_nand2);
Sensitive <<A << B;
}
};
Para que finalmente tengamos el EXOR, se
usan 4 módulos del tipo NAND, simplemente llamando al modulo NAND.
# include
“systemc.h”
# include
“nand2.h”
SC_MODULE(exor29
{
sc_in<bool> A, B;
sc_out<bool> F;
nand2 n1, n2, n3, n4;
sc_signal<bool>
S1, S2, S3;
SC_CTOR(exor) : n1(“N1”), n2(“N2”), n3(“N3”),
n4(“N4”),
{
n1.A(A);
n1.B(B);
n1.F(S1);
n2<< A << S1 <<
S2;
n3.(S1);
n3.(B);
n3.(S3);
n4.A(S2);
n4.B(S3);
n4.F(F);
}
};
Para Probar nuestro EXOR, esta el
siguiente codigo, que simula las entradas al EXOR.
#include
“systemc.h”
SC_MODULE
(stim)
{
sc_out<bool> A, B;
sc_in_clk Clk;
void StimGen()
{
A.write (false);
B.write (false);
wait ();
A.write (false);
B.write (true);
wait ();
A.write (true);
B.write (false);
wait ();
A.write (true);
B.write (true);
wait ();
sc_stop();
}
SC_CTOR(stim)
{
SC_CTHREAD(StimGen,
Cñk.pos());
}
};
El siguiente código, moritonea
la salida del EXOR.
#include
“systemc.h”
#include
“stim.h”
#include
“exor2.h”
#include
“mon.h”
int sc_main
(int argc, char* argv [])
{
sc_signal<bool> Asig, Bsig,
Fsig;
sc_clock TestClk(“TestClock”, 10,
SC_NS_0.5);
stim Stim1(“Stimulus”);
Stim1.A(Asig);
Stim1.B(Bsig);
Stim1.Clk(TestClk);
Exor2 DUT(“exor2”);
DUT.A(Asig) ;
DUT.B(Bsig) ;
DUT.F(Fsig) ;
mon Monitor1(“Monitor”)
Monitor1.A(Asig);
Monitor1.B(Bsig);
Monitor1.F(Fsig);
Monitor1.Clk(TestClk);
sc_start() ;
return 0;
}
La salida por consola, es la siguiente:
Time A B F
0 s 0 0 1
10 ns 0 0 0
20 ns 0 1 1
30 ns 1 0 1
40 ns 1 1 0