Diseño
y Programación Orientados a Objetos
1er. Sem 2013
Tarea 4: Compuertas Digitales como Objetos de Software en C++
Recomendación: Lea detenidamente la tarea. Si algo no lo
entiende, consulte en clases. Si es preciso, se incorporarán
aclaraciones al final.
Esta tarea tiene por objetivos:
* Ejercitar la configuración de un ambiente de trabajo para desarrollo
de aplicaciones en lenguaje C (puede usar Jgrasp
o Eclipse)
* Reconocer objetos de software como modelos de objetos reales.
* Reconocer clases y relaciones entre ellas en códigos fuentes C++.
* Ejercitar el diseño e implementación de una clase simple en C++.
* Ejercitar la extensión de clases dadas para satisfacer nuevos
requerimientos.
* Ejercitar la entrada y salida de datos en C++.
* Ejercitar una estrategia para programar simulaciones de fenómenos
discretos.
Descripción General
En esta tarea se modela la interacción entre compuertas digitales
básicas: NOT, OR, AND, NAND y NOR. Cada compuerta se modela según su
función lógica y un retardo fijo para cada compuerta. A partir de estos
modelos se construyen clases en Java que permiten crear objetos de
software para representar compuertas reales. Decimos que las clases
representan un modelo de la realidad pues no incorporamos todos los
elementos presentes en compuertas reales; por ejemplo, las transiciones
entre los niveles digitales se supondrán instantáneas. Veremos cómo
este modelo genera resultados "curiosos" cuando analizamos el circuito
de la figura 1:
Figura 1: Inversores interconectados: almacena 1 bit, sin control.
Modelos para los Objetos del Problema
Modelo de compuertas: Para
modelar cada compuerta usaremos una etapa de entrada y otra de salida.
La de entrada conoce el número de entradas de la compuerta y qué tiene
conectada en cada una. La otra etapa tiene sólo una señal de salida,
el retardo de propagación de la compuerta y un punto de conexión
externo. Todas las compuertas comparten al descripción de la etapa de
salida. Así podemos
definir la clase abstracta Gate para representar los aspectos comunes
de toda compuerta e incluir en ella al menos un método abstaracto que
permita calcular el valor lógico de salida que dependerá del número de
entrada y la lógica de cada compuerta en particular. Será responsabilidad
de cada subclase (Not, And, Or, etc) impementar ese método. En los archivos
Gate.h y Gate.cpp usted encontrará un modelo para la parte común de toda
compuerta lógica.
Modelo para la señales de entrada:
las entradas provendrán de un archivo de texto con líneas con el siguiente
formato:
<tiempo> <valor>
Se propone modelar cada fuente digital como una salida que varía según
los valores del archivo de entrada y cambia conforme pasa el tiempo. En
archivo Source.h usted encontrará el modelo para las fuentes
digitales.
Modelos para las interconexiones (cables):
En los circuitos digitales los cables tienen un flujo causal bien
definido. Así identificamos un punto desde cual proviene la señal
(from) y por ende está conectado a alguna salida digital y otro extremo
conectado a una entrada digital (to). Cabe destacar que no tiene
sentido considerar dos exitaciones para un mismo cable, pero en general
sí varias entradas digitales donde éste está conectado. Un cable es un
mero transportador de los valores lógicos desde una salida digital a
una o más entradas. Lo modelaremos sin retardo y sin estado lógico
propio. Cuando alguien se lo pida, éste lo obtendrá del valor lógico de
la salida digital que lo alimenta. En archivo Wire.h usted
encontrará el modelo para los cables.
Modelo para un instrumento de medición:
Para observar el valor de las señales en el tiempo es conveniente crear
algún modelo para un instrumento que registre la evolución de ciertas
variables lógicas. Es así como se modela un instrumento medidor a cuya
entrada se conectan los cables de interés registrar en el tiempo. Este
instrumento grabará en archivo los cambios de estado en el tiempo. En
archivo Meter.h usted encontrará un modelo para el instrumento
registrador.
Modelo para el avance del tiempo:
El tiempo es una variable continua; sin embargo, en los circuitos
digitales los estados cambian sólo cuando hay transiciones en las entradas y
éstas se dan en tiempos discretos. Así los cambios ocurren en instantes
discretos y no hay cambios de interés en otros instantes.
En presencia de variables con
cambios discretos en el tiempo,
como en las señales digitales, las simulaciones consideran avances no
regulares del tiempo y definidos según el evento de interés futuro más
próximo. En estos casos el algoritmo de simulación calcula los cambios
de estado bajo demanda de los objetos modelados que requieren cambio. En
cada iteración se pide actualización del objeto con actualización más
próximo en el futuro. Para ello el algoritmo hace uso de la esturtura
de datos Cola de Prioridad. Ésta es una cola donde los objetos
insertados deben tener una relación de orden. Se insertan en la cola
según se necesite y la operación para sacar elementos siempre extrae el
más pequeño de los insertados. Si la relación de orden es el tiempo en
que los cambios tendrán lugar, entonces al sacar objetos de la cola
obtendremos el primero cuyo estado debe ser actualizado.
En el caso de esta tarea, esa actualización afectará la
entrada de otras compuertas que deberán insertar eventos de
actualización futura en el cola. El tiempo futuro de actualización
depende del retardo de propagación de cada compuerta.
El algoritmo para un simulador de eventos discretos es del tipo:
simulate(PriorityQueue
& pq) {
ChangeEvent
&e;
// Objeto
ChangeEvent almacena referencia a objeto
//involucrado,
tiempo y valor de cambio futuro.
insertar_eventos_de_partida(pq); // primer cambio para cada fuente digital
e itinerar
//
cambios para condición inicial de cada compuerta.
while
( (e=pq.poll())!=null)
{ // mientras haya
eventos por procesar
Avanzar el tiempo;
Identificar
todos los eventos simultáneos para el tiempo actual;
Pedir a cada compuerta o fuente involucrada reflejar el nuevo valor en
salida;
Pedir a cada compuerta o fuente involucrada propagar la salida a nuevas
compuertas; // esto
gatilla
//nuevos
eventos de cambios itinerados en pq.
}
}
Resultados Esperados de su Grupo
Si
bien usted puede usar un IDE (Integrated Development Environment),
usted debe saber cómo compilar y correr su tarea dese la línea de
comandos.
Su tarea debe ser ejecutable en aragorn.elo.utfsm.cl usando:
$ make run
ante lo cual el programa pide:
1st. Source filename: <First input signal filename>
2nd. Source filename: <Second input signal filename>
Output filename: <Output signal filename>
Luego el programa corre hasta generar toda la salida indicada.
Para correr los circuitos de la figura 1 (pregunta b) y figura 2 (pregunta
d) usar
$ make run1
y
$ make run2
Usted deberá entregar los siguientes archivos:
- readme
- Archivo de Documentación: En éste usted responda las siguientes preguntas:
a) Para el código entregado analice el código del método simulate() de
la clase Simulator. Haga los gráficos de las señales para ver el efecto
de dejar sólo un llamado a log(currentTime) o dos (uno antes y otro después
de pfocesar los eventos). ¿Cuál es la ventaja de poner dos llamados en lugar
de
uno?. ¿Podría usted armar este circuito sin usar instancias de Wire?
b)
Cambie y el archivo DigitalCircuit1.cpp para simular el
circuito de la Figura 1. Incorpore un contador de instancias
activas de ChangeEvent. Su
objetivo
es identificar si todos los objetos creados en el Heap son
luego destruidos. Este programa no tiene archivos de entrada, sólo pida
el archivo de salida por consola. Además pida un límite para el tiempo
de simulación.Al término de su programa muestre por
pantalla
en número máximo de instancias creadas y el valor final de instancias
activas (debería ser cero en circuitos
que lleguen a estados estables). Haga los cambios necesarios si no
es el
caso. Utilice 2 [ns] (en realidad las unidades
de tiempo son irrelevantes) como retardo de cada inversor.
Muestre un diagrama temporal para la salida de ambos inversores.
c) Cree la clase And. Utilice los mismos tipos de constructores que en Or
d) Cree la clase Nand.
Usando esta implementación para la compuerta nand, cree un
DigitalCircuit2.cpp para el siguiente circuito:
Figura 2: FlipFlip D de canto positivo de reloj (tomado de
Wikipedia).
En su documentación muestre el diagrama temporal generado cuando
el reloj es de frecuencia igual a 20 veces el mayor retardo por usted
considerado y la señal Data también es cuadrada y de la mitad de la
frecuencia del reloj. Muestre 1,5 periodos de la señal D. No se
espera que su programa genere el diagrama temporal. Puede usar
el dibujo aquí incluido y el gráfico lo puede generar con una planilla
de cálculo a partir de los datos de salida de su programa.
- Códigos fuentes correspondiente a DigitaCircuit1.cpp de
la pregunta b), And.h, And.cpp de pregunta c), Nand.h, Nand.cpp y
DigitalCircuit2.java de pregunta d).
- La entrega de la tarea será a través de Assembla usando GIT. Para ello
revise esta documentación.
Ayudas
* Dé una mirada a la solución parcial del
problema. Si encuentra errores o algo que pueda ser mejorado, avise al
profesor.
* Como extensión para el archivo de salida use .csv.
Luego trate este archivo como si fuera planilla electrónica. Usted
podrá usar "tabs" como separador de columnas.
* No dude en consultar al profesor o ayudante sobre dudas de esta tarea.
* Espero esta tarea sea de
su interés y lo motive a hacer pruebas adicionales a las aquí pedidas,
se agradece; si embargo, sea cuidadoso, este ramo no es el único
donde usted debe rendir bien.