Diseño
y Programación Orientados a Objetos
1er. Sem 2013
Tarea 1: Compuertas Digitales como Objetos de Software
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 Java (se ha sugerido trabajar con Jgrasp, Eclipse o NetBeans )
* Reconocer objetos de software como modelos de objetos reales.
* Reconocer clases y relaciones entre ellas en códigos fuentes Java.
* Ejercitar el diseño e implementación de una clase simple.
* Ejercitar la extensión de clases dadas para satisfacer nuevos requerimientos.
* Ejercitar la entrada y salida de datos.
* Conocer el formato .csv y su importación a planillas electrónicas.
* Ejercitar la preparación y entrega de resultados de software
(creación de readme, documentación y agrupación de una
colección de archivos en uno "tar" o "zip").
* Aprender 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 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 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 lógica de cada compuerta en particular. Será responsabilidad
de cada subclase (Not, And, Or, etc) impementar ese método. En archivo
Gate.java 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.java 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.java 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.java 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 contínuas,
como la velocidad, aceleración, o posición, las simulaciones consideran
avances regulares del tiempo; por ejemplo, con incrementos en valor
delta (fijo o variable según el detalle que queramos). En casos
continuos la idea básica es discretizar el tiempo; para cada
instante discreto, se congela el tiempo y se pide a cada objeto
del modelo calcular cuál será su estado futuro (delta t más tarde)
a partir del estado actual y las condiciones a que está sometido. Es
importante congelar el tiempo y hacer este cálculo para cada objeto.
Luego se pide a todos actualizar su estado basado en lo calculado y
entonces se avanza el tiempo en ese delta. Esta idea simple trabaja
bien en muchas situaciones.
El algoritmo para un simulador de variables contínuas es del tipo:
simulate
( double delta_t, double endTime) { // Se presenta
por completitud, pero no se requeirirá en la tarea.
for (ElementoModelado e: listaDeTodosLosElementos)
e.setInitialState();
for (double t=0; t < endTime; t+=delta_t) {
for (ElementoModelado e: listaDeTodosLosElementos) // for each element
e.computeNextState(delta_t);
// compute next state
for (ElementoModelado e: listaDeTodosLosElementos) // for
each element
e.updateState();
// update its
state
}
}
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 por demanda de los objetos modelados que requieren cambio. En
cada iteración se pide actualización del objeto de 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 y tiempo de cambio
futuro.
insertar_eventos_de_partida(pq); // primer cambio para cada fuente digital.
while ( (e=pq.poll())!=null)
{ // mientras aún haya
eventos por procesar
e.update(pq);
// el evento más próximo
pide actualizar su estado,
}
// este proceso genera la inserción de nuevos eventos 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:
$ java DigitalCircuit <First input signal filename>
<Second input signal filename> <Output signal filename>
Luego el programa corre hasta generar toda la salida indicada.
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 meter.log() o dos (uno antes y otro después
de e.update()). ¿Cuál es la ventaja de poner dos llamados en lugar de
uno?
b) Para el código entregado para DigitalCircuit.java, vea el efecto de
incluir o no las líneas de código marcadas con /* b) */. Describa la
diferencia observada y por qué se produce.
b2) Para el circuito original entregado en DigitalCircuit.java, vea el efecto de las condiciones:
"if (output != newValue)" en método update() e "if (output
!= computeOutput())" en método inputChanged() , ambas en la clase Gate.
¿Se pueden eliminar? ¿Qué se gana con tenerlas?
c) Cambie y el archivo DigitalCircuit.java para simular el
circuito de la figura 1. 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.
¿Obtiene usted un estado estable? ¿Cómo explica usted el resultado?
d) Cree la clase And.java. Utilice los mismos tipos de constructores de Or.java
e) Cree la clase Nand.java, en este caso incluya el método:
void connectInput(Wire w);
Éste puede ser invocado cuantas veces desemos para crear así compuertas NAND de un número de entradas cualquiera.
Usando esta implementación para la conpuerta nand, cree un DigitalCircuit.java 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 D también es cuadrada y de la mitad de la
frecuencia del reloj. Muestre un 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 DigitaCircuit.java de
la pregunta c), And.java de pregunta d), Nand.java y
DigitalCircuit.java de pregunta e). Cree directorios de nombre
PreguntaC, PreguntaD, etc, para poner los códigos de cada pregunta.
- 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.