Emulador de Computador Digital

Anuncio
Proyecto Fin de Carrera
EMULADOR DE
COMPUTADOR DIGITAL
SIMPLE
Autor: Félix Robles Elvira
Tutor: José Ángel Acosta Rodríguez
Ingeniería de Telecomunicación
Departamento de Ingeniería de Sistemas y Automática
Escuela Técnica Superior de Ingeniería
Universidad de Sevilla
Dedicado a mis padres, a mis hermanos, a mi tutor José Ángel Acosta Rodríguez
por su ayuda, y a todos los amigos y familiares a los que les guste que les dediquen
proyectos n de carrera.
Índice
1. Introducción y objetivos
1
2. Elección del lenguaje de programación a usar
3
3. Fundamentos de un computador digital
5
3.1. Codicación binaria de la información . . . . . . . . . . . . . . . . . . .
5
3.1.1. Numeraciones binaria y decimal . . . . . . . . . . . . . . . . . .
5
3.1.2. Codicación de números enteros . . . . . . . . . . . . . . . . . .
6
3.2. Codicación de caracteres . . . . . . . . . . . . . . . . . . . . . . . . .
7
3.3. Álgebra de boole . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
8
3.3.1. Denición . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
9
3.3.2. Propiedades del álgebra de boole . . . . . . . . . . . . . . . . .
11
3.3.3. Funciones booleanas . . . . . . . . . . . . . . . . . . . . . . . .
11
3.3.4. Puertas lógicas . . . . . . . . . . . . . . . . . . . . . . . . . . .
12
4. Estructura general de un computador digital
15
4.1. Arquitectura de Von Neumann . . . . . . . . . . . . . . . . . . . . . . .
15
4.2. Almacenamiento de la información . . . . . . . . . . . . . . . . . . . .
16
4.3. Unidad de memoria central . . . . . . . . . . . . . . . . . . . . . . . . .
19
4.4. Unidad aritmético-lógica . . . . . . . . . . . . . . . . . . . . . . . . . .
21
4.5. Unidad de entrada y salida . . . . . . . . . . . . . . . . . . . . . . . . .
22
4.6. Enlaces o buses . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
23
4.7. Unidad de control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
24
5. Descripción de la máquina a implementar
27
5.1. Elementos del computador . . . . . . . . . . . . . . . . . . . . . . . . .
27
5.2. Funcionamiento del computador . . . . . . . . . . . . . . . . . . . . . .
29
5.2.1. Ejecución de instrucciones . . . . . . . . . . . . . . . . . . . . .
31
5.2.2. Instruciones de salto . . . . . . . . . . . . . . . . . . . . . . . .
33
5.2.3. Funcionamiento de la unidad de control . . . . . . . . . . . . . .
34
5.3. Código máquina . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
35
5.4. Lenguaje ensamblador . . . . . . . . . . . . . . . . . . . . . . . . . . .
36
5.5. Ejemplos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
40
5.5.1. Media de tres números . . . . . . . . . . . . . . . . . . . . . . .
40
4
5.5.2. Cálculo de número primo . . . . . . . . . . . . . . . . . . . . . .
41
5.5.3. Módulo al cuadrado de un vector . . . . . . . . . . . . . . . . .
43
5.5.4. Frase o palabra en orden inverso . . . . . . . . . . . . . . . . . .
44
5.5.5. Lectura de una matriz . . . . . . . . . . . . . . . . . . . . . . .
46
5.5.6. Submatriz triangular . . . . . . . . . . . . . . . . . . . . . . . .
48
6. Estructura del emulador
53
6.1. Código ensablador y código binario . . . . . . . . . . . . . . . . . . . .
53
6.2. Clases . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
54
6.2.1. Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
56
6.2.2. ProjectsManager . . . . . . . . . . . . . . . . . . . . . . . . . .
58
6.2.3. TabsManager . . . . . . . . . . . . . . . . . . . . . . . . . . . .
60
6.2.4. DebugViewManager . . . . . . . . . . . . . . . . . . . . . . . .
61
6.2.5. Sobre . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
65
6.2.6. Emulator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
66
6.2.7. VirtualComputer . . . . . . . . . . . . . . . . . . . . . . . . . .
69
6.2.8. ButtonTabComponent . . . . . . . . . . . . . . . . . . . . . . .
71
6.2.9. XenonHelper . . . . . . . . . . . . . . . . . . . . . . . . . . . .
72
6.2.10. LineCode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
73
6.2.11. Instruction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
74
6.2.12. PopupListener . . . . . . . . . . . . . . . . . . . . . . . . . . . .
76
6.2.13. Project . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
77
6.2.14. ProjectFile
. . . . . . . . . . . . . . . . . . . . . . . . . . . . .
77
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
78
6.2.16. JConnector . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
79
6.2.17. ConnectorContainer
. . . . . . . . . . . . . . . . . . . . . . . .
80
6.2.18. ConnectLine . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
81
6.2.15. Tab
7. Manual de usuario
83
7.1. Ejecución . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
83
7.2. Vista de desarrollo . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
83
7.3. Vista de emulación . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
86
7.4. Vista de depuración . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
88
5
8. Posibles ampliaciones
91
8.1. Interfaz gráca para plataformas móviles . . . . . . . . . . . . . . . . .
91
8.2. Ampliación del juego de instrucciones del computador . . . . . . . . . .
95
9. Conclusiones y cumplimiento de objetivos
103
10.Bibliografía
105
11.Anexos
107
11.1. Código . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
107
11.1.1. ButtonTabComponent.java . . . . . . . . . . . . . . . . . . . . .
107
11.1.2. JConnector.java
. . . . . . . . . . . . . . . . . . . . . . . . . .
109
. . . . . . . . . . . . . . . . . . . . . . . . . . .
112
11.1.4. ConnectLine.java . . . . . . . . . . . . . . . . . . . . . . . . . .
120
11.1.5. LineCode.java
. . . . . . . . . . . . . . . . . . . . . . . . . . .
125
11.1.6. Sobre.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
126
11.1.7. ConnectorContainer.java
. . . . . . . . . . . . . . . . . . . . .
128
11.1.8. PopupListener.java . . . . . . . . . . . . . . . . . . . . . . . . .
129
11.1.9. Tab.java
130
11.1.3. Emulator.java
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
11.1.10.DebugViewManager.java
. . . . . . . . . . . . . . . . . . . . .
132
. . . . . . . . . . . . . . . . . . . . . . . . . .
159
. . . . . . . . . . . . . . . . . . . . . . . . .
160
11.1.13.Project.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
165
11.1.14.VirtualComputer.java
. . . . . . . . . . . . . . . . . . . . . . .
166
11.1.15.Instruction.java . . . . . . . . . . . . . . . . . . . . . . . . . . .
208
11.1.16.ProjectsManager.java
. . . . . . . . . . . . . . . . . . . . . . .
213
11.1.17.XenonHelper.java . . . . . . . . . . . . . . . . . . . . . . . . . .
217
11.1.18.Interface.java . . . . . . . . . . . . . . . . . . . . . . . . . . . .
225
11.1.11.ProjectFile.java
11.1.12.TabsManager.java
6
Índice de guras
1.
Vista del gestor de versiones del software . . . . . . . . . . . . . . . . .
4
2.
Circuito de la suma de a y b . . . . . . . . . . . . . . . . . . . . . . . .
10
3.
Circuito simbólico del producto de a y b . . . . . . . . . . . . . . . . .
10
4.
Circuito simbólico de ā . . . . . . . . . . . . . . . . . . . . . . . . . . .
11
5.
Circuito con interruptores de ejemplo de función booleana . . . . . . .
12
6.
Símbolos de las puertas lógicas más comunes . . . . . . . . . . . . . . .
14
7.
Arquitectura de Von Neumann con un único bus . . . . . . . . . . . . .
16
8.
Estructura matricial de una memoria . . . . . . . . . . . . . . . . . . .
19
9.
Diagrama de bloques de la memoria principal . . . . . . . . . . . . . .
20
10.
Diagrama de bloques de una UAL, su acumulador, y señales de control
21
11.
Control de conexión de un dispositivo a un enlace con puertas triestado
24
12.
Esquema de una computadora digital mostrando los enlaces y las señales
de gobierno. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
27
13.
Fases de la ejecución de la instrucción suma. . . . . . . . . . . . . . . .
31
14.
Diagrama de bloques de la unidad de control . . . . . . . . . . . . . . .
34
15.
Cronograma de la instrucción suma . . . . . . . . . . . . . . . . . . . .
35
16.
Esquema del funcionamiento del programa que realiza media de tres
números . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
17.
Diagrama de funcionamiento delprograma que calcula si un número es
primo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
18.
42
Diagrama de funcionamiento delprograma que calcula el módulo al cuadrado de un vector de 4 componentes . . . . . . . . . . . . . . . . . . .
19.
41
44
Diagrama de funcionamiento de programa que escribe una frase en orden
inverso . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
46
20.
Diagrama de funcionamiento de programa que almacena una matriz . .
48
21.
Diagrama de funcionamiento de programa que lee una matriz y luego
escribe los elementos de su submatriz triangular . . . . . . . . . . . . .
51
22.
Diagrama de clases de las clases principales . . . . . . . . . . . . . . . .
56
23.
Diagrama de la clase Interface . . . . . . . . . . . . . . . . . . . . . . .
57
24.
Diagrama de la clase ProjectsManager . . . . . . . . . . . . . . . . . .
58
25.
Diagrama de la clase TabsManager . . . . . . . . . . . . . . . . . . . .
60
26.
Diagrama de la clase DebugViewManager . . . . . . . . . . . . . . . . .
62
27.
Diagrama de la clase Sobre . . . . . . . . . . . . . . . . . . . . . . . . .
66
7
28.
Diagrama de la clase Emulator . . . . . . . . . . . . . . . . . . . . . . .
66
29.
Diagrama de la clase VirtualComputer . . . . . . . . . . . . . . . . . .
69
30.
Diagrama de la clase ButtonTabComponent . . . . . . . . . . . . . . .
71
31.
Diagrama de la clase XenonHelper
. . . . . . . . . . . . . . . . . . . .
72
32.
Diagrama de la clase LineCode
. . . . . . . . . . . . . . . . . . . . . .
73
33.
Diagrama de la clase Instruction . . . . . . . . . . . . . . . . . . . . . .
74
34.
Diagrama de la clase PopupListener . . . . . . . . . . . . . . . . . . . .
76
35.
Diagrama de la clase Project . . . . . . . . . . . . . . . . . . . . . . . .
77
36.
Diagrama de la clase ProjectFile . . . . . . . . . . . . . . . . . . . . . .
77
37.
Diagrama de la clase Tab . . . . . . . . . . . . . . . . . . . . . . . . . .
78
38.
Diagrama de la clase JConnector . . . . . . . . . . . . . . . . . . . . .
79
39.
Diagrama de la clase ConnectorContainer . . . . . . . . . . . . . . . . .
80
40.
Diagrama de la clase ConnectLine . . . . . . . . . . . . . . . . . . . . .
81
41.
Vista inicial de desarrollo. . . . . . . . . . . . . . . . . . . . . . . . . .
84
42.
Ejemplo de desarrollo . . . . . . . . . . . . . . . . . . . . . . . . . . . .
85
43.
Barra de herramientas . . . . . . . . . . . . . . . . . . . . . . . . . . .
85
44.
Barra de menús de la vista de desarrollo . . . . . . . . . . . . . . . . .
86
45.
Vista de emulación . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
87
46.
Barra de herramientas de la vista de emulación . . . . . . . . . . . . .
87
47.
Barra de menús de la vista de emulación . . . . . . . . . . . . . . . . .
88
48.
Vista de depuración . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
89
49.
Barra de control de de la vista de depuración . . . . . . . . . . . . . . .
89
50.
Barra de menús de la vista de depuración . . . . . . . . . . . . . . . . .
90
51.
Traducción de texto a instrucciones ensamblador . . . . . . . . . . . . .
93
52.
Ejecución de una instrucción . . . . . . . . . . . . . . . . . . . . . . . .
94
53.
Cambios de constantes de la Clase Instruction . . . . . . . . . . . . . .
96
54.
Cambios en la enumeración OperationCode . . . . . . . . . . . . . . . .
96
55.
Cambios en Instruction::updateFromData() . . . . . . . . . . . . . . . .
98
56.
Cambios en Instruction::updateFromInstruction() . . . . . . . . . . . .
99
57.
Cambios en VirtualComputer::executeNextInstruction() . . . . . . . . .
100
58.
Cambios en VirtualComputer::executeNextInstruction() (continuación)
101
59.
Cambios en XenonHelper::translateToBinary() . . . . . . . . . . . . . .
101
60.
Cambios en XenonHelper::translateFromBinary() . . . . . . . . . . . .
102
8
Índice de cuadros
1.
Parte de la tabla ISO 8859-1 . . . . . . . . . . . . . . . . . . . . . . . .
8
2.
Algunos códigos de control . . . . . . . . . . . . . . . . . . . . . . . . .
8
3.
Tabla de la verdad de la suma de a y b . . . . . . . . . . . . . . . . . .
9
4.
Tabla de la verdad del producto de a y b . . . . . . . . . . . . . . . . .
10
5.
Tabla de la verdad de ā . . . . . . . . . . . . . . . . . . . . . . . . . . .
11
6.
Tabla de la verdad de ejemplo de función booleana . . . . . . . . . . .
12
7.
Tabla de la verdad de NO . . . . . . . . . . . . . . . . . . . . . . . . .
13
8.
Tabla de la verdad de O . . . . . . . . . . . . . . . . . . . . . . . . . .
13
9.
Tabla de la verdad de Y . . . . . . . . . . . . . . . . . . . . . . . . . .
13
10.
Tabla de la verdad de O negado . . . . . . . . . . . . . . . . . . . . . .
13
11.
Tabla de la verdad de Y negado . . . . . . . . . . . . . . . . . . . . . .
14
12.
Tabla de la verdad de O . . . . . . . . . . . . . . . . . . . . . . . . . .
14
13.
Tabla de transición del biestable RS . . . . . . . . . . . . . . . . . . . .
17
14.
Tabla de la verdad de circuito multiplicador . . . . . . . . . . . . . . .
22
15.
Ejemplo de instrucción . . . . . . . . . . . . . . . . . . . . . . . . . . .
30
16.
Ejemplo de programa en código máquina para el computador . . . . . .
36
17.
Las columnas indican el código de operación, modo de direccionamiento,
el código mnemotécnico y una somera explicación para cada una de las
instrucciones de CESIUS.
18.
. . . . . . . . . . . . . . . . . . . . . . . . .
38
Las columnas indican el código de operación, modo de direccionamiento,
el código mnemotécnico y una somera explicación para cada una de las
instrucciones de CESIUS (Continuación). . . . . . . . . . . . . . . . . .
19.
39
Ejemplo de programa. A la izquierda se presenta una lista de las operaciones a efectuar, a la derecha se tiene el programa en la memoria. El
contenido de los registros de la memoria se ha separado en tres bloques
(CO, MD y D) para facilitar el estudio, dicha separación no existe en la
realidad. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
39
20.
Código mnemoténico de programa que realiza media de tres números .
40
21.
Código Mnemotécnico de programa que calcula si un número es primo .
42
22.
Código Mnemotécnico de programa que calcula el módulo al cuadrado
de un vector de 4 componentes
. . . . . . . . . . . . . . . . . . . . . .
43
23.
Programa que escribe una frase en orden inverso . . . . . . . . . . . . .
45
24.
Programa que almacena una matriz . . . . . . . . . . . . . . . . . . . .
47
9
25.
Programa que lee una matriz y luego escribe los elementos de su submatriz triangular . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
26.
49
Programa que lee una matriz y luego escribe los elementos de su submatriz triangular (continuación)
. . . . . . . . . . . . . . . . . . . . . . .
10
50
11
1. Introducción y objetivos
En este proyecto se desarrolla una implementación emulada por software de una
computadora digital simple. La computadora solo existe a nivel virtual y a nivel teórico,
no existe una implementación tangible o física de dicha computadora. Dicha implementación virtual cuenta con un entorno de desarrollo, programa de traducción de código
ensamblador a código máquina, depurador y emulador. El esquema de funcionamiento de la computadora es simple, y ha sido desarrollado a partir del esquema de Von
Neumann para una computadora de programa almacenado.
El actual proyecto tiene como nombre clave Xenon, y está basado en el programa
antiguamente llamado CESIUS Arahal, Manuel R; Hernández, José Julio; Limón, Daniel
(1986)Acosta Rodriguez, José Ángel (2009). El proyecto consta de varias partes: el
programa desarrollado, su código fuente, y la documentación, siendo este documento la
última parte.
Los objetivos del proyecto son:
Diseño de una computadora simple y desarrollo de un programa software llamado
Xenon que permita emular dicha computadora. Dicho software habrá de incluir
un entorno de programación simple para escribir y compilar programas para el
computador, así como la posibilidad de depurar y ejecutar dichos programas.
Estudio de posibles ampliaciones de este proyecto.
El software Xenon ha de servir para mostrar el funcionamiento de las computadoras a personas que estén aprendiendo dicha materia.
El software Xenon ha de poderse ejecutar en diversas plataformas y sistemas
operativos, como pueden ser Windows, Linux, Mac.
La estructura del documento se detalla a continuación:
En el Capítulo 2 se razona el lenguaje de programación escogido para desarrollar
el emulador Xenon.
Explicación teórica del funcionamiento de los computadores digitales en los capítulo 3 y 4, basada en los apuntes de la asignatura de Informática Acosta Rodriguez,
José Ángel (2009).
1
Se realiza una descripción del computador a implementar en el capítulo 5, explicando los elementos del computador y su funcionamiento, el lenguaje de código
máquina, y el lenguaje ensamblador del computador.
El capítulo 6 trata de la estructura del proyecto de software Xenon, incluyendo
una descripción de las clases y métodos que contiene.
El manual de usuario del software Xenon está contenido en el capítulo 7.
El capítulo 8 detalla una descripción de posibles ampliaciones de este proyecto,
como la implementación del software para plataformas móviles como Android, o
ampliar el juego de instrucciones del computador emulado.
Las conclusiones del proyecto y análisis de los objetivos alcanzados se realiza en
el capítulo 9.
Siguen las referencias bibliográcas en el capítulo 10 y el código del emulador en
la parte de anexos correspondiente al capítulo 11.
2
2. Elección del lenguaje de programación a usar
El lenguaje escogido para desarrollar la aplicación ha sido Java. Las principales motivaciones para usar Java es permite la ejecución de un mismo programa en diversas
plataformas hardware y sistemas operativos, y la velocidad de ejecución es superior a la
de un lenguaje interpretado, acercándose a la velocidad que se consigue con lenguajes
compilados. Los lenguajes de programación compilados son más rápidos que los interpretados porque el código interpretado ha de ser reducido a código máquina en tiempo
real. Java compila el código, pero es compilado en bytecode, para una máquina que
realmente no existe, la Máquina Virtual Java (JVM). El código bytecode a su vez es
interpretado durante la ejecución del programa Java. Así pues la estrategia de Java es
mixta entre código interpretado y compilado. Comúnmente el código bytecode no es
simplemente interpretado, sino que usa compiladores just-in-time que traducen partes
del programa a código máquina de forma que puedan ejecutarse mucho más rápido que
si fueran interpretadas. Por todo esto, un programa Java suele ejecutarse más rápido
que un programa hecho para un lenguaje interpretado. Además, el programa compilado
a bytecode puede ejecutarse sin necesidad de recompilación en cualquier plataforma que
cuente con un intérprete de bytecode, como en los sistemas operativos Windows, Linux
y Mac.
Otras opciones son usar:
C/C++. Como desventaja principal, el ejecutable es dependiente del sistema operativo. La mayor ventaja radica en que es un lenguaje de más bajo nivel, lo que
permite crear ejecutables más rápidos.
Lenguajes intepretados, como python. Suelen ser multiplataforma, sin embargo
su ejecución, al ser lenguaje interpretado, es más lenta. Además requiere que
el usuario tenga instalado un intérprete, lo cual no siempre ocurre. Una posible
solución a ese problema sería realizar la aplicación web, de modo que sea el servidor
quien ejecute el código. Pero entonces estamos obligando al usuario a disponer
de conexión a internet, y al servidor a ejecutar el código de todos los usuarios, lo
cual puede sobrecargar el servidor.
Otra opción es implementar el emulador en una página web, por ejemplo haciendo
uso de javascript (otro lenguaje interpretado) en la parte del cliente para no
sobrecargar el servidor web.
3
Figura 1: Vista del gestor de versiones del software
A su vez, se ha hecho uso de un sistema de versiones en el desarrollo del software.
El uso de un sistema de versiones permite volver hacia atrás en el tiempo así como
saber exactamente en qué momento se escribió una parte del código o funcionalidad.
Los sistemas de control de versiones son muy útiles cuando el desarrollo de un software
es realizado por un equipo de varias personas, permitiendo añadir cambios locales a
una versión global. En proyectos de cierta envergadura, un sistema de versiones es casi
una necesidad. Este proyecto cuenta con más de 9000 líneas de código, por lo que no
haber hecho uso de un sistema de versiones habría dicultado el desarrollo del proyecto.
El sistema de versiones usado es Subversion, concretamente el cliente tortoisehg Varios
(2013). En la gura 1 se puede ver el entorno de dicho cliente subversion.
4
3. Fundamentos de un computador digital
A continuación se presenta un resumen de los fundamentos de un computador digital.
Para ello en primer lugar se dene cómo se puede codicar en forma binaria cualquier
información. Después se denen diferentes codicaciones de caracteres que se pueden
usar. En el siguiente apartado se describe el álgebra de boole, que permite denir
operaciones matemáticas y funciones haciendo uso de información binaria. Finalmente
se realiza una introducción a las puertas lógicas, que implementan funciones que usan
el álgebra de boole mediante circuitos electrónicos.
3.1. Codicación binaria de la información
Las computadoras digitales hacen uso de información en forma binaria. La razón
radica en que los dispositivos electrónicos usados en las computadoras hacen uso de
dos niveles de voltaje, correspondientes a los valores binarios 1 y 0. Sin embargo, las
computadoras son capaces de hacer uso de información de muchos tipos, como grácos,
textos y sonidos. Dicha información es posible Shannon, Claude E. (1948) representarla
en codicación binaria.
3.1.1. Numeraciones binaria y decimal
En el computador que aquí se presenta, solo se hacen uso de números enteros,
no maneja de forma directa números fraccionarios o de punto otante. El sistema de
numeración de uso más común es aquél en base 10, llamado sistema decimal. En el
sistema decimal, las cifras representan coecientes de un polinomio de potencias de 10.
A los coecientes di se les denomina dígitos.
D| 10 = dn ·10n + ...+d1 ·101 +d0 ·100
Por ejemplo, el número 9482 se descompone en:
9481 |10 = 9 · 103 + 4 · 102 + 8 · 101 + 1 · 100
En el sistema binario, la base es 2, y los únicos dígitos posibles son 0 y 1. A los
coecientes bi se les denomina bits.
B| 2 = bn ·2n + ...+b1 ·21 +b0 ·20
Por ejemplo, el número 11101 en base dos se puede descomponer:
11101 |2 = 1 · 24 + 1 · 23 + 1 · 22 + 0 · 21 + 1 · 20 = 29 |10
En general, el Teorema Fundamental de la Numeración permite construir números
en un sistema de numeración posicional en una base b cualquiera, siendo b un número
5
natural.
3.1.2. Codicación de números enteros
En un computador digital, la memoria está compuesta por celdas elementales que
corresponden con dígitos binarios, o bits. A su vez, una dirección de memoria en un
computador digital, o un registro, está formado por un grupo de celdas, de forma que
su conjunto permite codicar números tan grandes como la cantidad de bits del registro
permita, en una representación posicional en base 2.
Por ejemplo, si un registro tiene 16 celdas binarias, es posible almacenar en él números entre 0 y 216 − 1, es decir entre 0 y 65535. En general un computador digital hace
uso de registros de una cantidad de bits determinada, si bien ciertos registros pueden
tener un mayor o menor tamaño.
Si bien la representación binaria de un número entero positivo que acabamos de
explicar es ampliamente usado, existen diferentes opciones de representación de los
números enteros negativos:
Signo-valor absoluto: Una celda, normalmente la correspondiente al dígito más
signicativo, es aquella que indica si el número es positivo (con un 0) o negativo
(con un 1). De este modo, el resto de bits del registro, que se reeren al valor
absoluto del número, son los mismos tanto si el número es negativo como si es
positivo. En este sistema, el número cero tiene dos representaciones.
Complemento a 1: Se reserva el primer bit para el signo. Si el bit es positivo el resto
de números se representa en base dos, si es negativo s realiza el complemento bit a
bit (sustituir ceros por unos, y unos por ceros) del valor absoluto. En este sistema
también existen dos ceros. Por ejemplo, si existen 4 celdas, en complemento a 1:
0|10 = 0000 = 1111
3| 10 = 0011
-3|10 = 1100
Complemento a 2: El complemento a dos es igual que el complemento a 1 cuando
el número es positivo. Cuando el número es negativo, es como el complemento a
1 mas la unidad. En este caso solo existe una representación del cero, y tambien
es capaz de representar un número negativo más que las anteriores opciones.
Ejemplos de representación en complemento a dos con 4 celdas son:
6
0|10 = 0000
4| 10 = 0100
-4|10 = 1100
Se puede comprobar que, si el registro tiene n bits, y el número A es negativo, la
representación en complemento a 2 corresponde con A+2n . Por ejemplo:
-4|10 = 1100|complemento2 ≡ −4 + 24 = 12
Los dos primeros sistemas presentan dicultades para realizar operaciones aritméticas
elementales mediante el uso de circuitos electrónicos, es por ello que se ideó el sistema
de complemento a 2, que es ampliamente usado en los computadores digitales.
3.2. Codicación de caracteres
La mayoría de computadoras han de ser capaces de procesar, además de números,
caracteres de texto, como por eemplo:
Letras mayúsculas y minúsculas.
Dígitos.
Signos. Como por ejemplo + - , / ( ) . $ % = ¾ ? [ ] { }
Códigos que no tienen representación gráca, pero con funciones de control.
Existen multitud de códigs que permiten almacenar de forma binaria información de
este tipo, entre los que destaca el ASCII (American Standard Code for Information
Interchange), que asigna un número a cada signo. El ASCII necesita 7 bits por carácter,
siendo por tanto capaz de representar 128 signos diferentes. El ASCII extendido es una
versión posterior que hace uso de 8 bits, y es capaz de representar 256 signos.
Concretamente en el computador que se desarrolla en este proyecto, se hace uso del
código ISO 8859-1, que es una norma ISO que dene la codicación del alfabeto latino
e incluye los diacríticos (como las letras acentuadas, ñ y ç) Esta norma se caracteriza
por coincidir con la codicación ASCII en los primeros 128 caracteres, y añadir otros
128 más, haciendo uso de un total de 8 bits.
Se puede observar que las letras son asignadas un número en orden alfabético, y los
dígitos del 0 al 9 son asignados de forma consecutiva, así como que las mayúsculas se
asignan antes que las minúsculas. También cuenta con códigos de control, que no tienen
7
representación gráca y tienen un signicado especial. A continuación, en los cuadros
1 y 2 se representan algunos caracteres ISO 8859-1:
Dec
32
33
47
48
49
57
Signo
espacio
!
/
0
1
9
Dec
65
66
67
68
69
90
Signo
A
B
C
D
E
Z
Dec
97
98
99
100
101
122
Signo
a
b
c
d
e
z
Dec
169
225
233
237
243
250
Signo
©
á
é
í
ó
ú
Cuadro 1: Parte de la tabla ISO 8859-1
Dec
1
2
3
4
5
6
7
8
9
10
11
13
Abreviatura
SOH
STX
ETX
EOT
ENQ
ACK
BEL
BS
HT
LF
VT
CR
Transmisiones
Comienzo de cabecera
Comienzo de texto
Fin de texto
Fin de transmisión
Petición de transmisión
Reconocimiento de transmisión
Señal audible
Retroceso
Tabulación horizontal
Avance de línea
Tabulación vertical
Retorno de carro
Cuadro 2: Algunos códigos de control
3.3. Álgebra de boole
El álgebra de boole es un área del álgebra en que el valor de las variables son los
valores de verdad verdadero y falso, denotados como 0 y 1 comunmente. En álgebra
elemental, los valores de las variables son números y las principales operaciones son la
suma y multiplicación. En cambio, en el álgebra de boole las operaciones principales
son la conjunción (AND) y la disjunción (OR).
George Boole introdujo dicho álgebra en 1854Boole, George (1854). Más tarde, en
1938 Claude ShannonShannon, Claude E. (1937) encontró una aplicación de dicho álgebra a los circuitos eléctricos de conmutación. La lógica de boole tiene como aplicaciones
8
principales en el mundo de la computación el análisis y el diseño de circuitos. El análisis
de circuitos mediante álgebra de boole permite describir el funcionamiento de los mismos. El diseño permite desarrollar implementaciones concretas de funciones de dicho
álgebra.
La potencia del álgebra de boole en el campo de la computación proviene de que
tanto los circuitos digitales como el álgebra de boole hacen uso de información binaria,
donde la unidad elemental solo puede tomar dos valores: verdadero o falso, cero o uno.
3.3.1. Denición
Formalmente el álgebra de boole está compuesto por variables por y operaciones:
Una variable lógica tomará uno y solo un valor, entre dos opciones posibles. Esas
dos opciones posibles pueden ser cero o uno, o verdadero y falso matemáticamente,
o interruptor abierto e interruptor cerrado en un circuito, o un led encendido o
apagado.
Operaciones binarias. Una operación binaria sobre un conjunto es un cálculo sobre dos elementos de dicho conjunto, llamados operandos, y que producen otro
elemento del conjunto. Las operaciones básicas del álgebra de boole son:
ˆ Suma lógica. A+B, también llamado OR. El resultado es 1 si al menos uno de
los operandos vale 1, en otro caso el resultado es cero. El circuito de la gura
es un ejemplo simbólico de una implementación por medio de interruptores de
esta operación. También se incluye una tabla de la verdad de dicha operación.
En el cuadro 3 se representa la tabla de la verdad de la suma lógica y en la
gura 2 el circuito simbólico asociado.
a/b
0
1
0
0
1
1
1
1
Cuadro 3: Tabla de la verdad de la suma de a y b
ˆ Producto lógico. A·B, también llamado AND. El resultado es 1 si y solo
si ambos operadores valen 1, en otro caso el resultado es cero. El circuito
9
Figura 2: Circuito de la suma de a y b
de la gura es un ejemplo simbólico de una implementación por medio de
interruptores de esta operación.También se incluye una tabla de la verdad
de dicha operación. En el cuadro 4 se representa la tabla de la verdad del
producto lógico y en la gura 3 el circuito simbólico asociado.
a/b
0
1
0
0
0
1
0
1
Cuadro 4: Tabla de la verdad del producto de a y b
Figura 3: Circuito simbólico del producto de a y b
ˆ Negación lógica. a, también llamado NOT. El resultado es 1 si el operador
es 0, el resultado es 0 si el operador es 1. El circuito de la gura es un
ejemplo simbólico de una implementación por medio de interruptores de esta
operación.También se incluye una tabla de la verdad de dicha operación. En
el cuadro 5 se representa la tabla de la verdad de la negación lógica y en la
gura 4 el circuito simbólico asociado.
10
a
0
1
ā
1
0
Cuadro 5: Tabla de la verdad de ā
Figura 4: Circuito simbólico de ā
3.3.2. Propiedades del álgebra de boole
Las operaciones denidas tienen las siguientes propiedades:
Elementos neutros: Para la suma el cero es elemento neutro, es decir a+0 = a.
Para el producto el 1 es el elemento neutro pues a·1 = a.
Conmutatividad: Para la suma, se cumple que a + b = b + a. Para el producto
se cumple que a·b = b·a.
Asociatividad: Los paréntesis indican el orden en que se realizan una serie de
operaciones. La asociatividad implica que (a + b) + c = a + (b + c) para la
suma, y que (a·b)·c = a·(b·c) para el producto.
Distributividad: Es una propiedad que implica dos reglas válidas para reemplazar
una operación por otra. Implica que (a + b)·c = a · c + b · c y que a + (b · c) =
(a + b) · (a + c).
Leyes de Morgan, esta propiedad hace uso de las tres operaciones elementales del
álgebra de boole. Implica que a + b̄ = a · b y a · b = a + b.
3.3.3. Funciones booleanas
Una función es una expresión que contiene varias operaciones booleanas sobre un
conjunto de variables. Existirá un valor unívoco de la función dados unos valores concretos para las variables de la función. Existen varias formas de denir la función, una
forma es mediante el uso de operaciones sobre dichas variables, otra forma es mediante
una tabla de la verdad que explicite el valor de la función para todas y cada una de las
11
combinaciones de valores posibles de las variables de la función. Otra forma es mediante
un circuito con interruptores controlados por las variables de la función. Por ejemplo
una función f(a, b, c) se puede expresar de las siguientes formas:
f : (a, b, c) 7→ L = f (a, b, c) = a · b · c
a
0
0
0
0
1
1
1
1
b
0
0
1
1
0
0
1
1
c
0
1
0
1
0
1
0
1
L
0
0
0
0
0
0
0
1
Cuadro 6: Tabla de la verdad de ejemplo de función booleana
Figura 5: Circuito con interruptores de ejemplo de función booleana
3.3.4. Puertas lógicas
La equivalencia elemental entre elementos del álgebra de boole con los dispositivos
electrónicos de un computador digital está en las puertas lógicas, que son capaces de
realizar operaciones y funciones booleanas. Dichas puertas lógicas no contienen partes
móviles, sino que manejan el paso de señales mediante el uso de elementos electrónicos
como diodos y transistores, entre otros. En la gura 6 se representan los símbolos de
diferentes puertas lógicas. Las puertas lógicas elementales son:
NOT. También llamado puerta NO. La tabla de la verdad se puede ver en el
Cuadro 7.
OR. Llamada suma lógica o puerta O. La tabla de la verdad se puede ver en el
Cuadro 8.
12
a
0
1
ā
1
0
Cuadro 7: Tabla de la verdad de NO
a
0
0
1
1
b
0
1
0
1
a+b
0
1
1
1
Cuadro 8: Tabla de la verdad de O
AND. Producto lógico o puerta Y. La tabla de la verdad se puede ver en el Cuadro
9.
a
0
0
1
1
b
0
1
0
1
a·b
0
0
0
1
Cuadro 9: Tabla de la verdad de Y
NOR. También llamado O negado. La tabla de la verdad se puede ver en el Cuadro
10.
a
0
0
1
1
b
0
1
0
1
a+b
1
0
0
0
Cuadro 10: Tabla de la verdad de O negado
NAND. Llamado Y negado. La tabla de la verdad se puede ver en el Cuadro 11.
13
a
0
0
1
1
b
0
1
0
1
a·b
1
1
1
0
Cuadro 11: Tabla de la verdad de Y negado
XOR. Suma lógica exclusiva o puerta O exclusivo. La tabla de la verdad se puede
ver en el Cuadro 12.
a
0
0
1
1
b
0
1
0
1
a ⊕b
0
1
1
0
Cuadro 12: Tabla de la verdad de O
Figura 6: Símbolos de las puertas lógicas más comunes
14
4. Estructura general de un computador digital
En este capítulo se describe la estructura de un computador digital sencillo. Para
ello primero se introduce la arquitectura de Von Neumann, que es la arquitectura que
usa el computador digital en que se enmarca este proyecto. A continuación se describen
los principios básicos del almacenamiento de datos en una computadora digital.Después,
se introduce el funcionamiento de diferentes elementos que componen un computador
con la arquitectura de Von Neumann:
La unidad de memoria central, que es la unidad principal de almacenamiento del
computador.
La unidad aritmético-lógica, que permite realizar operaciones matemáticas con
datos.
La unidad de entrada y salida se encarga de comunicar al computador con el
exterior, ya sea con otras computadoras o periféricos.
Los enlaces y buses, cuya función es conectar todos los demás elementos del
computador.
La unidad de control, cuya tarea es coordinar y hacer uso de los demás elementos
del computador para ejecutar cada instrucción correctamente.
4.1. Arquitectura de Von Neumann
La computadora digital que en este proyecto se desarrolla tiene una arquitectura de
Von Neuman. El modelo de Von Neumann, o la arquitectura de Princeton deriva de la
descripción de una arquitectura de computador digital realizada por el cientíco John
von Neumann en 1945 von Neumann, John (1945). En dicha arquitectura existe una
unidad de proceso consistente en una unidad aritmético-lógica, una serie de registros del
procesador, una unidad de control que contiene un registro de instrucción y un contador
de programa, una memoria para guardar instrucciones, un sistema de almacenamiento
externo masivo y mecanismos de entrada y salida de datos.
La arquitectura describe un computador de programa almacenado donde la búsqueda de instrucciones y el desarrollo de operaciones sobre datos no pueden ocurrir de
forma simultánea porque comparten un bus común. Esta limitación se conoce como el
cuello de botella de Von Neumann y a menudo limita el rendimiento del sistema. Otras
15
arquitecturas, como la llamada arquitectura de Harvard, no presentan dicho cuello de
botella, pues presentan caminos diferentes para el almacenamiento y encaminamiento
de señales de instrucciones y de datos.
En general, un computador de programa almacenado mantiene sus instrucciones
programadas y sus datos en memoria de acceso aleatorio con capacidad de escritura y
lectura. La mayoría de los computadores modernos almacenan los datos y las instrucciones en una misma memoria. La gura 7 muestra un esquema de la arquitectura de
Von Neumann con un único bus.
Figura 7: Arquitectura de Von Neumann con un único bus
4.2. Almacenamiento de la información
Un computador necesitará guardar en algún dispositivo la información si quiere
poder procesarla. Como antes hemos dicho, la unidad fundamental de información de
un computador digital es el bit, o dígito binario. El dispositivo físico elemental que es
capaz de almacenar un bit se denomina celda o célula elemental.
Existen diversos tipos de dispositivos físicos capaces de almacenar un bit. Entre ellos
se encuentran los biestables. Los biestables suelen realizarse mediante circuitos electrónicos basados en las puertas lógicas que ya hemos analizado, pero la principal diferencia
radica en que los biestables tienen memoria. Es decir, las salidas de un biestable no solo
dependen de las entradas, sino del estado en que se encuentra, es decir dependen del
valor de sus entradas anteriores. Este tipo de circuitos se llaman circuitos secuenciales.
Entre los diversos tipos de biestables se encuentra el biestable RS. Se puede denir
para el biestable RS una tabla de transición, que da la salida y(t1 ) en el instante t1 a
16
partir de las entradas RS y la salida y(t0 ) en el instante anterior t0 . El cuadro 13 muestra
la tabla de transición del biestable RS.
RS→
y(t0 )=0
y(t0 )=1
00
0
1
01
1
1
10
0
0
11
X
X
Cuadro 13: Tabla de transición del biestable RS
El valor X para la columna RS=11 indica que el biestable no ha de usarse con esas
entradas. La entrada S signica set y como se puede observar en la table, pone a 1 el
biestable. La entrada R signica reset y pone a cero el biestable. Si ambas entradas
están a cero, la salida del biestable será conservada.
Si bien las celdas son las unidades elementales de memoria, para representar números
mayores a 1 o 0 es necesario hacer uso de conjuntos de celdas, que componen un registro.
Como ya se ha mencionado, un registro corresponde con una representación posicional
en base 2 de un número. Por ejemplo un registro de 11 células será capaz de representar
211 =2048 números diferentes.
Al equiparar un conjunto de biestables con el concepto de registro, es a menudo
necesario que cuando dicho registro es actualizado todas las celdas se actualicen de
forma coordinada, de forma que añadimos a los biestables una entrada de sincronismo.
En el contexto de la memoria principal de un computador digital, se denen diferentes unidades de memoria, de entre las cuales ya hemos visto varias:
Bit: Unidad elemental de información binaria y que se almacena en una celda
elemental
Byte u octeto: Formada por 8 bits, y necesita por tanto de 8 celdas de memoria.
Palabra: La información almacenada en un registro de un computador se denomina palabra. Un registro puede tener cualquier número de celdas, si bien los más
usuales son de 16, 32, y 64 bits o 2, 4, y 8 bytes.
En la arquitectura de Von Neumann la memoria permite tanto almacenar datos como
instrucciones y se denen 3 operaciones de memoria:
Direccionamiento: Selecciona la información de un sector de memoria a partir de
la posición (dirección) de ese sector en la memoria.
17
Lectura: Lleva a cabo una copia de la información que existen en un sector de la
memoria a otro bloque del computador, como un registro o un bus. En general
la lectura es no destructiva, de forma que tras la lectura del dato, el mismo sigue
almacenado en memoria.
Escritura: Almacena información en un sector de memoria. Es una operación
destructiva de forma que el dato que había almacenado previamente en memoria
es destruido y reemplazado por un nuevo dato.
Existen multitud de tipos de memorias, y multitud de clasicaciones, entre otras:
Tiempo de acceso: Según el tiempo que transcurre desde que se ordena la operación de memoria hasta que ésta termina.
Capacidad: Se reere a la cantidad de información que es capaz de almacenar la
memoria. Se suele hacer uso de los prejos kilo- y mega-, entre otros.
Modo de acceso: Dene las formas en que se accede a la información, por ejemplo:
ˆ Acceso directo: para acceder al dato basta con acceder a una posición de
memoria conocida. El tiempo de acceso en este caso es independiente de
dónde se encuentra el dato.
ˆ Acceso indirecto: Para acceder al dato es necesario acceder a una posición de
memoria que nos indicará en qué posición de memoria se encuentra el dato.
ˆ Acceso secuencial: Para acceder al dato hemos de leer o dejar pasar la información que le precede.
Volatilidad: Indica si la información almacenada puede ser modicada o destruida
cuando no se suministra energía a la memoria. Las memorias de semiconductores
suele ser volátil, y la de discos y cintas suele ser no volátil.
Papel de la memoria en el computador:
ˆ Memoria principal: En ella se almacena el programa que se está ejecutando,
en general es volátil y de acceso directo y está implementada con circuitos
de semiconductores.
18
ˆ Memoria auxiliar: Suele ser mucho más masiva, no volátil y suele tener un
mayor tiempo de acceso. Estos dispositivos se consideran periféricos y por
ello es necesario una unidad de adaptación llamada de entrada y salida para
conectarla con el computador.
Figura 8: Estructura matricial de una memoria
La memoria principal suele implementarse con una serie de registros, todos del
mismo tamaño, en una disposición matricial. Recordemos que el ancho del registro
es también la longitud de una palabra en el computador. En la disposición matricial,
cada columna representa un bit de cada registro, y el número de las es el número
de registros. El número de las suele ser mucho mayor al de columnas, y suele ser un
múltiplo de base 2. A su vez cada la, es decir, cada registro, corresponde con una única
dirección de memoria, de forma que para realizar una operación de lectura o escritura
sobre ese registro basta con conocer la dirección de dicho registro. Si, por ejemplo, una
memoria tiene 210 registros de 16 bit cada uno, la capacidad de la memoria, en bits es
de 16·210 = 16384 bits. La gura 8 muestra la estructura matricial de una memoria.
La selección de una dirección de memoria es un paso que hay que realizar antes de la
lectura/escritura de dicho registro. El elemento de la memoria que se encarga de realizar
la selección es el decodicador de direcciones. Si por ejemplo existen 210 direcciones de
memoria, para seleccionar una dirección concreta habrá que pasar una dirección de 10
bits al decodicador de direcciones.
4.3. Unidad de memoria central
La unidad de memoria central contiene tanto las instrucciones del programa a ejecutar como los datos almacenados por el usuario. La gura 9 presenta el diagrama de
bloques de la memoria principal. Los bloques de la unidad de memoria central son:
19
S. Es el registro que se encarga de seleccionar una dirección de memoria. Si existen
2m direcciones de memoria, el registro S tendrá un tamaño de m bits.
LECM, ESCM. Señales de control, LECM de lectura, y ESCM de escritura.
T. Registro de almacenamiento temporal. En caso de realizar una lectura de la
memoria, el dato leído será almacenado en este registro. En caso de escritura en
memoria, será el dato de este registro el que será escrito en memoria. El tamaño
de este registro coincide con el tamaño de los registros de la memoria.
Figura 9: Diagrama de bloques de la memoria principal
Es decir, para realizar una operación de lectura:
En primer lugar es necesario seleccionar la posición de memoria que vamos a leer.
Para ello introducimos la dirección de memoria en el registro S.
Después activamos la señal LECM, de forma que el dato de la dirección seleccionada es copiado al registro T.
Finalmente copiamos el contenido del registro T al lugar de destino (un bus u
otro registro).
Los pasos para una operación de escritura son parecidos:
En primer lugar es necesario seleccionar la posición de memoria en la que vamos
a escribir. Para ello introducimos la dirección de memoria en el registro S.
Copiamos el dato que queremos escribir en el registro T.
20
Finalmente copiamos el contenido de T en la posición adecuada en la memoria,
activando la señal de control ESCM.
4.4. Unidad aritmético-lógica
Un elemento muy importante del computador digital es la unidad aritmético lógica.
Esta unidad es capaz de realizar operaciones aritméticas y lógicas sobre una o varias
señales de entrada. Para ello hace uso de circuitos electrónicos con puertas lógicas y del
álgebra de boole. Algunas operaciones aritméticas comunes de una UAL son la suma,
resta, multiplicación o división. Ejemplo de operaciones lógicas son comparaciones de
igualdad. La gura 10 representa el diagrama de bloques de una UAL.
Figura 10: Diagrama de bloques de una UAL, su acumulador, y señales de control
De forma frecuente, el resultado de las operaciones de la UAL se guarda en un
registro Acumulador, el cual a su vez se retroalimenta como operando de la UAL. De
este modo, por ejemplo, para realizar una suma:
Primero se lleva el primer operando a la UAL, y con la señal de control CARGA
el operando pasa al acumulador.
Después se lleva el segundo operando a la entrada de la UAL.
Como el primer operando está en el Acumulador y éste está retroalimentado a la
UAL, en este momento los dos operandos están como sendas entradas de la UAL,
por lo que ahora se activa la señal de control SUMA, realizando de forma efectiva
la suma.
21
Finalmente el resultado, que está en el acumulador, se puede transferir a otros
elemenos del computador.
Puesto que el resultado de la UAL solo depende de las señales de control y operandos
de entrada en un momento dado, para crear una UAL simple basta con hacer uso de
circuitos combinacionales. Por ejemplo, un circuito multiplicador de números de dos
bits tiene la tabla de la verdad del cuadro 14, que habrá que implementar con puertas
lógicas:
a1
0
0
0
0
0
0
0
0
1
1
1
1
1
1
1
1
a0
0
0
0
0
1
1
1
1
0
0
0
0
1
1
1
1
b1
0
0
1
1
0
0
1
1
0
0
1
1
0
0
1
1
b0
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
m3
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
1
m2
0
0
0
0
0
0
0
0
0
0
1
1
0
0
1
0
m1
0
0
0
0
0
0
1
1
0
1
0
1
0
1
1
0
m0
0
0
0
0
0
1
0
1
0
0
0
0
0
1
0
1
Cuadro 14: Tabla de la verdad de circuito multiplicador
4.5. Unidad de entrada y salida
Las computadoras interaccionan con el exterior por medio de los periféricos. Esta
interacción con el exterior es necesaria para que una computadora resulte de alguna
utilidad. Los periféricos más comunes son el teclado y la pantalla.
Una característica típica de los periféricos es la diferente velocidad o tasa de transmisión de datos entre diferentes periféricos. El computador ha de ser capaz de tratar
con periféricos que se comunican con éste a muy diversas velocidades. Por ejemplo,
una pantalla puede necesitar recibir varios megabits de datos por segundo y un teclado normalmente no va a enviar más de 20 caracteres por segundo. Por lo general,
22
son los propios periféricos los que cuentan con los adaptadores necesarios para poderse
comunicar con el computador de forma adecuada.
El computador digital que aquí se desarrolla cuenta solo con dos periféricos: un
teclado y una pantalla. Otros periféricos comunes para computadoras digitales son el
ratón, la impresora y dispositivos de almacenamiento masivo.
Teclado de computador. Es un dispositivo con botones o teclas dispuestas de forma
similar a en una máquina de escribir, que actúan como conmutadores electrónicos.
La pulsación de dichas teclas, ya sea de forma individual o de forma combinada,
es detectada por el teclado y manda al computador señales codicadas de caracteres de texto, números y señales de control. Dicha información es leída de forma
periódica por el computador. La velocidad de transmisión de los teclados suele
ser baja (del orden de 10 caracteres por segundo).
Monitor de visualización. Es una pantalla electrónica de visualización de datos.
Cuando un programa quiere que el usuario reciba datos, éstos son mandados al
monitor o pantalla. Existen multitud de tipos de pantallas, como por ejemplo las
pantallas de tubos de rayos catódicos y las pantallas planas LCD. A su vez las
pantallas pueden comunicarse a más o menos velocidad con el computador, si bien
por lo general la velocidad de transmisión requerida por una pantalla es superior
a la requerida por un teclado. El uso de un monitor requiere de un dispositivo
llamado tarjeta de vídeo que funcione como intermediario y adaptador entre ésta
y el computador. La resolución de la pantalla, la cantidad de colores disponibles,
así como el ratio de refresco de la misma, son factores que imponen requerimientos
mínimos en la cantidad de memoria y potencia de cálculo necesarias para que un
computador pueda hacer uso de una pantalla.
4.6. Enlaces o buses
Los enlaces, o buses en inglés, cumplen el objetivo de conectar los diferentes elementos del computador. La forma más básica de conectar una serie de dispositivos es conectarlos todos con todos, pero si tenemos n dispositivos eso signica tener
n(n−1)
conexiones
2
bidireccionales, con lo que el número de conexiones necesarias para un número no muy
grande de dispositivos es poco factible.
En un bus de datos, varios dispositivos se conectan a un mismo bus, y en un momento
dado solo existirá una fuente de datos, pudiendo recibir esos datos todos los demás
23
dispositivos. Es decir, un dispositivo hablará y los demás estarán a la escucha. Los
enlaces entre dispositivos mediante un mismo bus tienen diversas ventajas, entre ellas:
Número reducido de conexiones necesarias.
Simplicación del sistema, de forma que cada dispositivo solo necesita una entrada
y una salida.
Facilidad para la expansión, es decir, facilidad para añadir mas dispositivos.
Facilidad de implementación en circuitos electrónicos.
Posibilidad de que los dispositivos se encuentren a distancias grandes unos de
otros.
Figura 11: Control de conexión de un dispositivo a un enlace con puertas triestado
A su vez los buses tienen algunos inconvenientes, como un mayor tiempo de transmisión, ya que varios dispositivos que quieran transmitir a la vez no podrán hacerlo,
alguno tendrá que esperar. Para evitar colisiones de mensajes, existen protocolos que
por ejemplo delimitan los momentos en que los dispositivos pueden comenzar a hablar.
En general, por cada dispositivo existirá una señal de gobierno que marcará si el
dispositivo accede al bus (ya sea para leer o para escribir en él). La señal de gobierno
se suele conectar a puertas triestado, de forma que cuando la señal de gobierno es cero,
la salida uctúa libremente tomando el valor que otro dispositivo le impone, y cuando
es uno, la puerta transmite la información a la salida. La gura 11 representa el control
de conexión de un dispositivo a un enlace con puertas triestado.
4.7. Unidad de control
La unidad de control se encarga de interpretar las instrucciones a ejecutar, y mandar
las señales de control necesarias a los elementos correspondientes del computador, en el
24
tiempo y orden adecuados según la instrucción. Es decir, la ejecución de una instrucción
se realiza activando señales de gobierno, a las que se denomina microórdenes. Estas
microórdenes se ejecutan todas dentro de un solo ciclo de reloj (el tiempo de ejecución
de una instrucción, por lo general).
Se denomina cronograma de operaciones de una instrucción a la representación
temporal de la evolución de las distintas señales de gobierno y control activadas en
dicha instrucción. Cada arquitectura de computador tiene cronogramas diferentes para
cada instrucción, pues dichos cronogramas dependen de la arquitectura especíca del
computador. En la próxima sección se desarrollará la unidad de control especíca del
computador que describe este documento.
Un tipo de unidades de control es el llamado unidad de control cableada. Esta unidad
se implementa con una serie de circuitos lógicos y biestables que activa y desactiva las
señales de control y gobierno en el momento adecuado en cada tipo de instrucción.
Como cada instrucción necesita de un cronograma diferente, el circuito de las unidades
de control cableadas suele ser complejo, sobre todo cuantas más instrucciones diferentes
implemente el computador. Otro tipo de unidades de control son las unidades de control
microprogramadas, que hacen uso de una micro-memoria, eliminando la complejidad
del sistema.
25
26
5. Descripción de la máquina a implementar
Este capítulo describe el computador que el software Xenon ha de implementar. En
la primera sección se enumeran los elementos de dicho computador, incluyento entre
otros los registros y las señales de control. Sigue un apartado que explica cómo procede
la ejecución de una instrucción del computador. A continuación se describe el código
máquina del computador, que es el código binario que maneja el computador. Después
se detalla el código ensamblador, que es un lenguaje simbólico más sencillo de usar por
una persona que el código máquina. El capítulo termina con una serie de ejemplos de
programas escritos en lenguaje ensamblador.
5.1. Elementos del computador
Figura 12: Esquema de una computadora digital mostrando los enlaces y las señales de
gobierno.
El computador implementa una arquitectura basada en la de Von Neumann, donde
los periféricos de la unidad de entrada y salida son la pantalla y el teclado. Los elementos
con que cuenta el computador y que aparecen en la gura 12 son:
1. Un enlace M que une la memoria, la unidad de control y la UAL. La información
que se o transmite puede ser de diversas clases: datos y resultados de operaciones,
instrucciones del programa y direcciones de memoria.
2. Otro enlace S que une la unidad de control y el selector de posiciones de memoria.
Por él se transmiten direcciones de memoria.
3. La memoria principal, con organización matricial.
27
4. La UAL con registro acumulador que almacena uno de los operandos y el resultado
de las operaciones.
5. Los siguientes registros:
A. Registro acumulador de la UAL.
S. Registro de selección de memoria.
T. Registro tampón de comunicación entre la memoria y la línea M.
P. Contador de pasos de programa. Indica la posición dentro de la memoria
de la o instrucción a ejecutar.
I. Registro de instrucción. Guarda en cada momento la instrucción que se
ejecuta en o o ese paso.
E. Registro de comunicación con el exterior. Permite tomar datos del teclado
o llevarlos o a la pantalla. Es una forma simple e idealizada de la unidad de
control que se ha descrito anteriormente.
6. Las señales del computador:
EA. Señal de escritura en el registro A. Guardará en A el resultado de la
ALU. Si además de EA, la señal EO está activada pero las señales SUMA,
RESA, MULTA, DIVA y MODA no están activadas, la ALU leerá el bus M
y será el dato del bus M el que se guarde en el registro A.
SA. Permite escribir el dato del registro A en el bus M.
EO. Asigna el dato del bus M a la entrada de la ALU.
SUMA. Realiza la operación suma A+M en la ALU de los datos de A y del
bus M (si la señal EO está activada).
RESA. Realiza la operación resta A−M en la ALU de los datos de A y del
bus M (si la señal EO está activada).
MULTA. Realiza la operación multiplicación A·M en la ALU de los datos de
A y del bus M (si la señal EO está activada).
DIVA. Realiza la operación división A/M en la ALU de los datos de A y del
bus M (si la señal EO está activada).
28
MODA. Realiza la operación división Amod M en la ALU de los datos de A
y del bus M (si la señal EO está activada).
INCP. Incrementa P en una unidad.
EP. Asigna al registro P el valor del bus S.
SP. Escribe el valor del registro P en el bus S.
ES. Escribe el valor del bus S en el registro S, seleccionando dicha posición
de memoria.
SD. Escribe el valor del registro D (los 11 bits menos signicativos del registro
I) en el bus S.
EI. Escribe el valor del bus M en el registro I.
LECM. Lee la posición de memoria seleccionada por el registro S y la escribe
en el registro T.
ESCM. Escribe el valor del registro T en la posición de memoria seleccionada
por el registro S.
ET. Escribe el valor del bus M en el registro T.
ST. Escribe el valor del registro T en el bus M.
EE. Escribe el valor del bus M en el registro E.
SE. Escribe el valor del registro E en el bus M.
LEET. Lee el valor de los datos de entrada del teclado y lo escribe en el
registro E.
ESCP. Muestra en la consola el valor del registro E.
5.2. Funcionamiento del computador
Como ya se ha mencionado con anterioridad, el computador que aquí se presenta es
una máquina de programa almacenado, de modo que en la memoria se almacenan tanto
datos como instrucciones.El computador cuenta con la mayoría de los dispositivos ya
mencionados, conectados a través de enlaces de tipo bus, permitiendo la transferencia
de información de un dispositivo a otro. La unidad de control es el elemento que envía
órdenes a todos los demás.
El programa se encuentra almacenado en memoria, con las instrucciones situadas
de forma secuencial. La unidad de control se encargará de ir leyendo y ejecutando las
29
instrucciones del programa en el orden adecuado. La unidad de control cuenta con un
registro P que guarda la posición de memoria de la instrucción que se ejecuta. En general
el valor del registro P se incrementa en una unidad tras ejecutar cada instrucción, si
bien existen como excepciones las instrucciones de salto.
El registro P sirve para localizar la instrucción a ejecutar. Después de ser localizada
en memoria, dicha instrucción se copia al registro I. Entonces la unidad de control
interpreta la instrucción y activa las señales de gobierno que correspondan con dicha
instrucción en el orden adecuado.
Una instrucción, que al n y al cabo es un número que es guardado en el computador
en binario, se puede dividir en tres partes:
Código de operación (CO): Indica la operación a realizar. En este computador
consta de 4 bits, de modo que existen hasta 16 operaciones diferentes.
Modo de direccionamiento (MD): El computador trabajará con modos de direccionamiento directo e indirecto. Como solo trabajaremos con esos dos posibles
modos de direccionamiento, usaremos 1 bit para indicar el modo. En el modo
directo el operando es la dirección del dato, o de la posición de memoria donde
se guardará el resultado de la operación.
Dirección de memoria u operando: Esta dirección tendrá diferentes signicados
dependiendo del código de operación y del modo de direccionamiento. Por ejemplo,
en la suma directa indica la dirección de memoria donde se encuentra el dato a
sumar. La dirección de memoria consta de 11 bits.
En total una instrucción está formada por 16 bits, que a su vez es la longitud de
cada registro en la memoria principal. A su vez, las direcciones de memoria tienen una
longitud de 11 bits, lo cual permite direccionar 211 =2024 direcciones de memoria, de
forma que la memoria principal tiene una capacidad total de 16·2048 = 32738 bits = 4
kilobytes.
Como ejemplo, podemos analizar la instrucción del cuadro 15:
CO
0101
MD
0
D
000 0000 1000
Cuadro 15: Ejemplo de instrucción
El código de operación 0101 indica en este caso sumar al acumulador el contenido
de una dirección de memoria. El modo de direccionamiento 0 es directo, de forma que
30
el el dato a sumar se encuentra en la dirección 000 0000 1000, que corresponde en base
2 con la dirección 8.
5.2.1. Ejecución de instrucciones
La ejecución de cada instrucción se divide en 4 fases. Las fases corresponden con
acciones diferentes en cada instrucción. Estas fases se representan en la gura 13 para
el caso sencillo de una suma.
Figura 13: Fases de la ejecución de la instrucción suma.
Búsqueda de la instrucción. En la gura P indica que la instrucción está en la
dirección de memoria 17. Se direcciona dicha posición de memoria copiado P al
registro S. Luego realiza una lectura y se copia el contenido de la memoria en esa
posición al registro I, que pasa a contener la dirección a ejecutar.
Búsqueda del operando. En este caso el operando está en la posición de memoria
8, luego el computador direcciona dicha posición copiando 8 al registro S.
Ejecución de la instrucción. El contenido de memoria en dicha posición es leído
y se traslada al registro de operando de la UAL. Entonces se realiza la suma del
acumulador con el operando, y dicha suma se guarda en el registro acumulador.
Preparación de la siguiente instrucción. Se incrementa en una unidad el registro
P, que pasará a contener la posición de memoria de la siguiente instrucción.
31
La ejecución de una instrucción es dirigida por la unidad de control mediante cambios
en las señales de gobierno, que permiten realizar tanto operaciones como transferencias
entre registros. Una descripción más formal de la ejecución de una instrucción es aquella
en que se detallan las transferencias entre los registros, a la vez que las operaciones aritméticas y de lectura y escritura en memoria. Por ejemplo, la ejecución de la instrucción
descrita anteriormente se puede describir de la siguiente forma:
Búsqueda de la instrucción. Se lee de memoria la instrucción a ejecutar, que está
en la dirección que indica el registro P. Las operaciones elementales a realizar son:
ˆ Direccionamiento: Transferir a S el contenido de P, se simboliza mediante
(P)→S.
ˆ Lectura de memoria: Se transere al registro T el dato guardado en la posición de memoria direccionada: M(S)→T
ˆ Transferencia del registro T al registro I, que es el registro que la unidad de
control interpreta como instrucción: T→I
Búsqueda del operando: En la instrucción de este ejemplo, el código de operación
corresponde a una suma, y el direccionamiento es directo, de forma que el operador
está en la posición de memoria que indica D. Para leer el operando:
ˆ Direccionamiento de D: (D)→S.
ˆ Lectura de memoria: M(S)→T. Lee la posición de memoria direccionada,
copiándola al registro T.
Ejecución de la instrucción. Se realiza la operación de suma y ésta se guarda en
el registro acumulador. Es decir, (T)+(A)→A.
Preparación de la siguiente instrucción. En el caso de la suma, la siguiente instrucción viene dada por P+1, de modo que P+1 →P.
Este método de representación de operaciones consiste en detallas las transferencias
elementales entre registros. Es importante recalcar que dichas transferencias y operaciones son llevadas a cabo por la unidad de control mediante la activación coordinada,
por parte de dicha unidad de control, de las diversas señales de gobierno que posee el
computador. Por ejemplo, para escribir en el registro T será necesario activar ET y para
leer T habrá que activar ST.
32
5.2.2. Instruciones de salto
En multitud de instrucciones, tras su ejecución el registro P contador de pasos se
incrementa en la unidad. Existe otro tipo de instrucciones que realizan saltos entre
instrucciones, de una posición de memoria a otra. Por ejemplo, la instrucción de salto
incondicional carga en P la dirección del operando de dicha instrucción, de forma que
tras esta instrucción será la instrucción situada en esa posición la que se ejecutará. De
este modo, los pasos de ejecución de la instrucción salto incondicional son:
Búsqueda de la instrucción. Se lee la instrucción que se va a ejecutar a partir del
conocimiento de su posición en la memoria, dato contenido en el registro P.
ˆ Direccionamiento: Transferir a S el contenido de P, se simboliza mediante
(P)→S.
ˆ Lectura de memoria: Se transere al registro T el dato guardado en la posición de memoria direccionada: M(S)→T
ˆ Transferencia del registro T al registro I, que es el registro que la unidad de
control interpreta como instrucción: T→I
Búsqueda del operando. El operando de la instrucción es directamente D, de forma
que no hace falta acceder a la memoria principal para acceder al operando.
Ejecución de la instrucción. En este caso solo es necesario transferir el contenido
de D al registro P. (D)→P
Preparación de la siguiente instrucción. Normalmente esto signicaría modicar
el registro P, pero en el caso de las instrucciones de salto esto ya se realiza en la
fase de ejecución de la instrucción, así que en esta fase no hacemos nada.
Si bien la instrucción de salto incondicional es la más sencilla dentro de las instrucciones
de salto, existen instrucciones de salto llamadas condicionales, de forma que el resultado
de la ejecución de la instrucción, esto es el contenido del registro P, será uno u otro
dependiendo de si se cumple cierta condición. Esta condición puede ser por ejemplo
una comparación. Este tipo de instrucciones es importante a la hora de realizar lo que
se denominan bifurcaciones en un programa.
33
5.2.3. Funcionamiento de la unidad de control
La unidad de control de interpretar las instrucciones a ejecutar y activar las señales
de gobierno o control adecuadas para asegurar su ejecución. Como ya se ha mencionado
la ejecución de cada instrucción se divide en una serie de etapas, en las cuales se activarán unas señales de gobierno u otras dependiendo de la instrucción que se esté tratando
(concretamente dependiendo del código de operación y modo de direccionamiento). La
activación de las señales de gobierno en el transcurso de la ejecución de la instrucción
se denomina microórdenes. La gura 14 muestra un diagrama de la unidad de control.
Las microórdenes tienen como objetivo realizar transferencias entre registros, así
como realizar operaciones sobre el contenido de los mismos. La complejidad de un
cronograma depende de factores como la cantidad de registros del computador, la complejidad de la UAL o la diversidad de instrucciones que implementa el computador. El
diseñador de la computadora tendrá que encargarse de realizar el cronograma de cada
instrucción, y a partir de él crear un diseño de circuitos combinacionales y secuenciales
que implemente físicamente la unidad de control.
El circuito de la unidad de control suele ser complejo y como ya se ha mencionado
con anterioridad existe otra opción para su realización, ideada por Wilkes, que trata de
evitar dicha complejidad haciendo uso de una memoria especial donde se guarden las
microórdenes.
Figura 14: Diagrama de bloques de la unidad de control
Para visualizar el trabajo de la unidad de control es útil representar el estado de
las señales de gobierno utilizadas por la instrucción a través del tiempo, en lo que se
denomina un cronograma. En los cronogramas, el eje horizontal representa el transcurso
del tiempo y en el vertical se representa el voltaje o estado activado/alto y desactivado/bajo de las diferentes señales. A su vez, en la parte superior se ha representado la
señal de reloj del computador.
34
La señal de reloj ha sido dividida en cuatro diferentes fases (θ1 ,θ2 ,θ3 ,θ4 ), que a su
vez pueden ser agrupadas en dos etapas principales:
Ciclo de instrucción. Ocupa las fases θ1 y θ2 . Se lee de la memoria principal la
instrucción a ejecutar y se carga en el registro I.
Ciclo de operando. Ocupa las fases θ3 yθ4 y en dicho ciclo se realiza la búsqueda del
operando, la ejecución de la operación, y la preparación de la siguiente instrucción.
Figura 15: Cronograma de la instrucción suma
5.3. Código máquina
Las instrucciones que procesa un computador digital forman un lenguaje del tipo
denominado código máquina o código binario. Recordemos que el computador digital
maneja solo números binarios, de modo que el código máquina es directamente escrito en
binario. Como el código máquina del juego de instrucciones del computador, los lenguajes de código máquina son muy dependientes de la arquitectura de cada computador, y
por tanto el código de un programa es difícilmente transportable a otras arquitecturas.
El lenguaje de código máquina es el tipo de lenguaje más primitivo en que un
programa se puede escribir, y por ello es un lenguaje de bajo nivel, pues no está pensado
para que sea fácil de usar y entender por parte de un humano y es poco transportable.
Los lenguajes de más alto nivel son más transportables y fáciles de entender por las
personas. Una ventaja de los lenguajes de código máquina es que permiten escribir los
programas de la forma más eciente.
El computador en que se enmarca este proyecto tiene una longitud de instrucción
de 16 bits, que como ya se ha explicado se divide en 3 partes: el código de operación,
el modo de direccionamiento y el operador o dirección. El código de operación cuenta
con 4 bits, el modo de direccionamiento de un bit y el operador cuenta con 11 bits.
35
En el cuadro 16 se puede ver el código de un pedazo de un programa. El programa
leerá dos números del teclado, los guardará en las posiciones de memoria 10 y 11, los
sumará y guardará el resultado en la posición de memoria 12, para nalmente mostrar
el resultado en pantalla.
Si bien este programa es muy simple, realizar programas no mucho más complejos
en código binario se hace una tarea demasiado tediosa y cada vez más difícil. Por esa
razón se diseñaron lenguajes cada vez más sencillos de usar y entender. El próximo paso
en facilidad de uso es el código mnemotécnicos.
Dirección
50
CO
0100
MD
0
D
000 0000 1010
51
0100
0
000 0000 1011
52
0010
0
000 0000 1010
53
0101
0
000 0000 1011
54
0001
0
000 0000 1100
55
0011
0
000 0000 1100
56
0000
0
000 0000 0000
Signicado
Leer del teclado un número
y guardarlo en la posición
de memoria 10
Leer del teclado un número
y guardarlo en la posición
de memoria 11
Llevar al acumulador el
valor de la posición de
memoria 10
Sumar al acumulador el
número guardado en la
posición de memoria 11
Almacenar el valor del
acumulador en la posición
de memoria 12
Escribir en pantalla el valor
de la posición de memoria
12
Parar la máquina
Cuadro 16: Ejemplo de programa en código máquina para el computador
5.4. Lenguaje ensamblador
Un lenguaje ensamblador es un lenguaje de programación de bajo nivel que se usa
para programara computadores, microprocesadores, microcontroladores etc. Implementa una representación simbólica (o código mnemotécnico) de los códigos de máquina
binarios, así como de una serie de pseudoinstrucciones. El código máquina ha de ser
traducido a código máquina por un programa de traducción. Mientras que la traduc-
36
ción de los códigos mnemotécnicos a código máquina es directa, las pseudoinstrucciones
requieren que el programa traductor realice tareas adicionales durante la traducción,
como por ejemplo situar constantes en posiciones concretas de la memoria, situar ciertas instrucciones a partir de cierta posición de memoria o traducción de etiquetas del
código ensamblador a posiciones de memoria de código máquina.
Tanto las instrucciones del procesador como los registros y posiciones de memoria,
y las pseudoinstrucciones, son especícos de cierta arquitectura de computador, con lo
que el código generado no es directamente portable a otra arquitectura diferente. Esta
es una característica común en lenguajes de bajo nivel.
El lenguaje ensamblador de la máquina virtual implementada en este proyecto cuenta con las instrucciones denidas en los cuadros 17 y 18. En el cuadro 19 se muestra un
ejemplo de programa en código ensamblador.
A su vez el lenguaje ensamblador implementa las siguientes pseudoinstrucciones:
ORG Sirve para indicar en qué dirección de memoria comenzarán a colocarse las
instrucciones y espacios para datos y resultados al realizarse la traducción. Permite
al programador o indicar de forma simple dónde va a ir ubicado su programa
dentro de la memoria.
ESP Sirve para dejar un espacio en la memoria en el cual no habrá ninguna
Este tipo de espacios se utiliza para datos y resultados.
instrucción.
CTE Es similar a ESP pero además deja un valor en el espacio. Permite tener
constantes que el programa vaya a necesitar, por ejemplo el número
dos en caso
de que se necesite realizar una media, etc.
FIN Indica al traductor que cese la traducción. No debe confundirse con ALT que
es la instrucción de parada de la máquina.
DRE Signica Dirección Representada por la Etiqueta. Guarda como constante
en memoria la posición de memoria en que se encuentra la etiqueta que toma
como parámetro esta pseudoinstrucción.
37
CO
MD
Código
Operación realizada
0000
0001
0
0
ALT
ALM
0001
1
ALMI
Parar la máquina
Almacenar el contenido del
acumulador en la memoria
Almacenar indirectamente
0010
0
CAR
0010
0011
1
0
CARI
ESC
0011
1
ESCI
0100
0100
0101
0
1
0
LEE
LEEI
SUM
Cargar de la memoria al
acumulador
Cargar indirectamente
Escribir un entero en la
pantalla
Escribir indirectamente un
entero en la pantalla
Leer un entero del teclado
Leer indirectamente
Sumar al acumulador
0101
1
SUMI
Sumar indirectamente
0110
0
RES
Restar al acumulador
0110
1
RESI
Restar indirectamente
0111
0111
0
1
MUL
MULI
Multiplicar por A
Multiplicar indirectamente
1000
0
DIV
1000
1
DIVI
Dividir el acumulador entre
el operando
Dividir indirectamente
1001
0
MOD
1001
1
MODI
1010
1010
0
1
SAL
SALI
Módulo del acumulador o y
el operando
Módulo realizado o
indirectamente
Salto incondicional
Salto incondicional
indirecto
Transferencia entre
registros
(A)→M(D), P→(P) + 1
(A)→M(M(D)), P→(P) +
1
M(D)→A, P→(P) + 1
M(M(D))→A, P→(P)+ 1
M(D)→E, P→(P) + 1
M(M(D))→E, P→(P) + 1
E→M(D), P→(P) + 1
E→M(M(D)), P→(P)+1
(A) + M(D)→A, P→(P) +
1
(A) + M(M(D))→A,
P→(P) + 1
(A) - M(D)→A, P→(P) +
1
(A) - M(M(D))→A,
P→(P) + 1
(A)·M(D)→A, P→(P) + 1
(A)·M(M(D))→A,
P→(P) + 1
(A) / M(D)→A, P→(P) +
1
(A) / M(M(D))→A,
P→(P) + 1
(A) mod M(D)→A, P→(P)
+1
(A) mod M(M(D))→A,
P→(P) + 1
(D)→P
M(D)→P
Cuadro 17: Las columnas indican el código de operación, modo de direccionamiento, el
código mnemotécnico y una somera explicación para cada una de las instrucciones de
CESIUS.
38
CO
MD
Código
Operación realizada
1011
0
SAN
Salto si A es negativo
1011
1
SANI
1100
0
SAC
Salto indirecto si A es
negativo
Salto si A es cero
1100
1
SACI
Salto indirecto si A es cero
1101
0
SAP
Salto si A es positivo
1101
1
SAPI
1110
0
ECA
1110
1
ECAI
1111
1111
0
1
LCA
LCAI
Salto indirecto si A es
positivo
Escribir carácter a en la
pantalla
Escribir carácter a
indirectamente
Leer carácter
Leer carácter a
indirectamente
Transferencia entre
registros
(D)→P si (A)<0
si no P→(P) + 1
M(D)→P si (A)<0
si no P→(P) + 1
(D)→P si (A)=0
si no P→(P) + 1
M(D)→P si (A)=0
si no P→(P) + 1
(D)→P si (A)>0
si no P→(P) + 1
M(D)→P si (A)>0
si no P→(P) + 1
M(D)→E, P→(P) + 1
M(M(D))→E, P→(P) + 1
E→M(D), P→(P) + 1
E→M(M(D)), P→(P)+1
Cuadro 18: Las columnas indican el código de operación, modo de direccionamiento, el
código mnemotécnico y una somera explicación para cada una de las instrucciones de
CESIUS (Continuación).
Instrucción
LEER
LEER
CARGAR
SUMAR
ALMACENAR
ESCRIBIR
PARAR
10
11
10
11
12
12
Dirección
20
21
22
23
24
25
26
CO
0100
0100
0010
0101
0001
0011
0000
MD
0
0
0
0
0
0
0
D
00000001010
00000001011
00000001010
00000001011
00000001100
00000001100
00000000000
Cuadro 19: Ejemplo de programa. A la izquierda se presenta una lista de las operaciones
a efectuar, a la derecha se tiene el programa en la memoria. El contenido de los registros
de la memoria se ha separado en tres bloques (CO, MD y D) para facilitar el estudio,
dicha separación no existe en la realidad.
39
5.5. Ejemplos
5.5.1. Media de tres números
Este programa calcula la media de tres números. Primero el programa pide tres números, los cuales almacena en memoria. Después calcula la media y nalmente muestra
en pantalla dicha media. El cuadro 20 presenta el código ensamblador del programa, y
la gura 16 el esquema de funcionamiento del mismo.
A:
B:
C:
TRES:
RES:
INI:
ORG
SAL
ESP
ESP
ESP
CTE
ESP
LEE
LEE
LEE
CAR
SUM
SUM
DIV
ALM
ESC
ALT
FIN
0
INI
1
1
1
3
1
A
B
C
A
B
C
TRES
RES
RES
Cuadro 20: Código mnemoténico de programa que realiza media de tres números
40
Figura 16: Esquema del funcionamiento del programa que realiza media de tres números
5.5.2. Cálculo de número primo
Este programa comprueba si un número es primo. En primer lugar el programa pide
un número N al usuario, que es guardado en memoria. Después el programa calcula si
el resto de dividir N entre los números 2 a N-1 es cero para alguno de ellos, en cuyo
caso N no sería primo. Si N es primo, el programa escribirá '0' en pantalla. Si es primo,
escribirá '1' en pantalla. El cuadro 21 presenta el código ensamblador del programa, y
la gura 17 el esquema de funcionamiento del mismo.
41
PRIMO:
CONTADOR:
SI:
NO:
INI:
BUCLE
PRINTSI:
PRINTNO:
ORG
SAL
ESP
CTE
CTE
CTE
LEE
CAR
RES
SAC
CAR
MOD
SAC
CAR
SUM
ALM
SAL
ESC
ALT
ESC
ALT
FIN
0
INI
1
2
1
0
PRIMO
PRIMO
CONTADOR
PRINTSI
PRIMO
CONTADOR
PRINTNO
CONTADOR
SI
CONTADOR
BUCLE
SI
NO
Cuadro 21: Código Mnemotécnico de programa que calcula si un número es primo
Figura 17: Diagrama de funcionamiento delprograma que calcula si un número es primo
42
5.5.3. Módulo al cuadrado de un vector
Este programa calcula el módulo de un vector de cuatro componentes. El programa
pide cuatro números como datos de entrada, los cuales guarda en memoria. Después
calcula la suma de los cuadrados de las componentes del vector, es decir, el módulo al
cuadrado del vector. Finalmente el programa muestra el número calculado en pantalla.
El cuadro 22 presenta el código ensamblador del programa, y la gura 18 el esquema
de funcionamiento del mismo.
VECTOR:
TAM:
RES:
PUN:
VPOS:
UNO:
INI:
LEER:
PRINT:
ORG
SAL
ESP
CTE
ESP
ESP
DRE
CTE
CAR
ALM
CAR
SUM
RES
SAC
LEEI
CARI
MULI
SUM
ALM
CAR
SUM
ALM
ESC
ALT
FIN
0
INI
4
4
1
1
VECTOR
1
VPOS
PUN
VPOS
TAM
PUN
PRINT
PUN
PUN
PUN
RES
RES
PUN
UNO
PUN
RES
Cuadro 22: Código Mnemotécnico de programa que calcula el módulo al cuadrado de
un vector de 4 componentes
43
Figura 18: Diagrama de funcionamiento delprograma que calcula el módulo al cuadrado
de un vector de 4 componentes
5.5.4. Frase o palabra en orden inverso
Este programa pide caracteres como datos de entrada, los cuales guarda en memoria,
hasta que el usuario escriba un punto. Entonces el programa escribe los caracteres introducidos en orden inverso. El cuadro 23 presenta el código ensamblador del programa,
y la gura 19 el esquema de funcionamiento del mismo.
44
P:
PUNTO:
VPOS:
UNO:
INI:
LEER:
PRINT:
PARAR:
FRASE:
ORG
SAL
ESP
CTE
DRE
CTE
CAR
ALM
LCAI
CARI
RES
SAC
CAR
SUM
ALM
SAL
CAR
RES
SAC
CAR
RES
ALM
ECAI
SAL
ALT
ESP
FIN
0
INI
1
46
FRASE
1
VPOS
P
P
P
PUNTO
PRINT
P
UNO
P
LEER
P
VPOS
PARAR
P
UNO
P
P
PRINT
100
Cuadro 23: Programa que escribe una frase en orden inverso
45
Figura 19: Diagrama de funcionamiento de programa que escribe una frase en orden
inverso
5.5.5. Lectura de una matriz
Este programa guarda en memoria una matriz. Para ello primero pide dos números
'm' y 'n' como parámetros de entrada, que corresponden con el número de las y columnas de dicha matriz. Se supone que m · n < 50. A continuación el usuario introduce los
elementos de dicha matriz. El cuadro 24 presenta el código ensamblador del programa,
y la gura 20 el esquema de funcionamiento del mismo.
46
M:
N:
MATA:
DCM:
K:
J:
PUN:
UNO:
INI:
BUCLK:
BUCLJ:
ORG
SAL
ESP
ESP
ESP
DRE
ESP
ESP
ESP
CTE
LEE
LEE
CAR
ALM
CAR
ALM
CAR
RES
MUL
SUM
RES
SUM
ALM
LEEI
CAR
SUM
ALM
RES
SAN
SAC
CAR
SUM
ALM
RES
SAN
SAC
ALT
FIN
0
INI
1
1
50
MATA
1
1
1
1
M
N
UNO
K
UNO
J
K
UNO
N
J
UNO
DCM
PUN
PUN
J
UNO
J
N
BUCLJ
BUCLJ
K
UNO
K
M
BUCLK
BUCLK
Cuadro 24: Programa que almacena una matriz
47
Figura 20: Diagrama de funcionamiento de programa que almacena una matriz
5.5.6. Submatriz triangular
Programa que lee una matriz y luego escribe los elementos de su submatriz triangular inferior en el orden indicado en la gura. La submatriz triangular inferior está
formada por los elementos de la diagonal de la matriz y los de debajo. Los cuadros
25 y 26 presenta el código ensamblador del programa, y la gura 21 el esquema de
funcionamiento del mismo.
48
M:
N:
MATA:
DCM:
K:
J:
PUN:
UNO:
INI:
BUCLK:
BUCLJ:
BSK:
ORG
SAL
ESP
ESP
ESP
DRE
ESP
ESP
ESP
CTE
LEE
LEE
CAR
ALM
CAR
ALM
CAR
RES
MUL
SUM
RES
SUM
ALM
LEEI
CAR
SUM
ALM
RES
SAN
SAC
CAR
SUM
ALM
RES
SAN
SAC
CAR
ALM
CAR
ALM
0
INI
1
1
50
MATA
1
1
1
1
M
N
UNO
K
UNO
J
K
UNO
N
J
UNO
DCM
PUN
PUN
J
UNO
J
N
BUCLJ
BUCLJ
K
UNO
K
M
BUCLK
BUCLK
UNO
K
UNO
J
Cuadro 25: Programa que lee una matriz y luego escribe los elementos de su submatriz
triangular
49
BSJ:
CAR
RES
MUL
SUM
RES
SUM
ALM
ESCI
CAR
SUM
ALM
RES
SAN
SAC
CAR
SUM
ALM
RES
SAN
SAC
ALT
FIN
K
UNO
N
J
UNO
DCM
PUN
PUN
J
UNO
J
K
BSJ
BSJ
K
UNO
K
M
BSK
BSK
Cuadro 26: Programa que lee una matriz y luego escribe los elementos de su submatriz
triangular (continuación)
50
Figura 21: Diagrama de funcionamiento de programa que lee una matriz y luego escribe
los elementos de su submatriz triangular
51
52
6. Estructura del emulador
El programa desarrollado es un emulador de un computador digital sencillo denominado Xenon, que cuenta con las instrucciones de código máquina que se han descrito
en secciones previas. Este programa está implementado en lenguaje Java, lo cual permite que un mismo ejecutable pueda ser usado sin modicación alguna en muy diversas
arquitecturas y sistemas operativos. Este programa no solo sirve como emulador de
dicho computador, sino como plataforma de desarrollo y depuración de aplicaciones en
lenguaje ensamblador para dicho computador. Existen tres partes diferenciadas en este
programa, que corresponden con tres vistas diferentes de la aplicación:
Vista de desarrollo: Esta vista permite al usuario crear y gestionar proyectos y
código ensamblador, además de permitir acceder al resto de vistas. Desde esta
vista será posible compilar el código ensamblador para pasarlo a código binario.
Vista de depuración: Desde la vista de depuración, el usuario puede controlar
la ejecución de un programa. El depurador puede abrir tanto archivos en código
ensamblador como en código binario.
Vista de emulación: Esta vista abre el emulador del computador digital. Puesto
que el computador digital solo entiende código binario, el emulador solo es capaz
de ejecutar código binario.
La sección de manual de usuario describe de forma más detallada el aspecto visual de
cada vista. Tal y como describe la sección de manual de usuario, el programa cuenta
con dos ejecutables. El ejecutable xenon.main.jar abre la vista de desarrollo, desde la
cual se puede acceder a las demás vistas. El ejecutable xenon.emu.jar es una versión
standalone del emulador, de forma que no sea necesario abrir el entorno de desarrollo
para emular la ejecución de un programa en el computador digital.
6.1. Código ensablador y código binario
Los dos lenguajes que entiende este computador son el código ensamblador y el
código binario denidos en anteriores secciones. Sin embargo, como el computador digital descrito, llamado Xenon, no tiene implementación física, estos códigos han de ser
guardados por el emulador en algún formato que sea capaz de entender el programa
emulador.
53
El código ensamblador es guardado en cheros de texto, de forma que cada instrucción es contenida en una línea. El tamaño de estos cheros dependerá de cuántas
líneas de código tenga dicho programa. El código ensamblador es guardado en cheros
de texto con extensión ls2.
En cambio, el código binario es guardado en un archivo binario. Recordemos que
el computador tiene una capacidad de direccionamiento de la memoria principal de 11
bits, contando con 2048 posibles direcciones de memoria. A su vez la longitud de un
registro de memoria es de 16bits, o 2 bytes.Los cheros de código binario contienen una
copia del contenido de toda la memoria principal del computador. Estos archivos están
en formato binario, de modo que los primeros 2 bytes corresponden a la dirección de
memoria 0, los siguientes 2 bytes corresponden a la dirección de memoria 1 y así hasta
llegar a la última dirección de memoria, 2047. Como se puede comprobar, el formato de
los archivos de código binario del computador Xenon es muy sencillo. Dichos cheros
tienen una extensión ece que los identica. Además, todos los archivos de código
binario tendrán el mismo tamaño, pues el tamaño de la memoria principal no cambia y
los archivos de código binario contienen una copia bit a bit de dicha memoria, de forma
secuencial.
6.2. Clases
El código está documentado en doxygen van Heesch, Dimitri (1997), de forma que
sea fácil de entender. Las clases principales implementadas en el código son:
Interface. Es la clase principal del ejecutable xenon.main.jar, por ello contiene una
función main. Dene una ventana que contiene un JPanel con un CardLayout,
que permite alternar entre las vistas de desarrollo y depuración dentro de una
misma ventana.
ProjectsManager. Gestiona el árbol de proyectos de la vista de desarrollo.
TabsManager. Gestiona las pestañas de los archivos abiertos en la vista de desarrollo.
DebugViewManager. Implementa la vista de depuración.
Sobre. Esta clase implementa una ventana popup que muestra información sobre
el autor del proyecto, así como del profesor tutor del mismo.
54
Emulator. Es la clase principal del ejecutable xenon.emu.jar, por ello contiene una
función main. Esta clase es la principal de la vista de emulación. La vista de emulación es accesible tanto desde la vista de desarrollo del ejecutable xenon.main.jar
como desde el ejecutable xenon.emu.jar de forma standalone.
ButtonTabComponent. Esta clase es usada por cada pestaña, en la vista de desarrollo. Permite mostrar el nombre del archivo de una pestaña, así como un botón
con una X que sirve para cerrar dicha pestaña.
XenonHelper. En esta clase se encuentran métodos que permiten compilar código
ensamblador, así como la lectura e interpretación de código binario.
Instruction. Una instancia de esta clase contendrá toda la información de una
instrucción: la posición de memoria en que se encuentra, el código de operación
y el operador de la instrucción.
PopupListener. Implementa un listener que muestra un popup cuando se hace
click derecho con el ratón en cierto objeto.
Project. Dene un proyecto y sus propiedades básicas.
ProjectFile. Dene un chero perteneciente a un proyecto.
Tab. Implementa una pestaña que muestra un archivo, en la vista de desarrollo.
VirtualComputer. Es una abstracción del funcionamiento del computador Xenon.
El emulador y el depurador usan una instancia de esta clase para ejecutar cada
instrucción.
Las siguientes clases tienen como objetivo conectar visualmente con líneas y echas
componentes grácos en un JPanel, de forma sencilla. Este código es una modicación
del código de Stanislav Lapitsky Lapitsky, Stanislav (2007).
JConnector. Clase principal del conector que conecta dos objetos con echas.
ConnectorContainer. Extensión de JPanel que permite añadir conectores con echas entre objetos contenidos en dicho JPanel.
ConnectLine. Dene una línea usada por un JConnector.
55
Para hacerse una primera idea de la estructura del programa, la gura 22 es un diagrama
de clases UML del código que incluye las clases anteriormente mencionadas. Cuando
dos clases son conectadas por una echa, como DebugViewManager→VirtualComputer,
signica que DebugViewManager tiene un atributo que es una instancia de la clase
VirtualComputer. A su vez, a un lado de dicha echa se sitúa el nombre de dicho
atributo.
Figura 22: Diagrama de clases de las clases principales
6.2.1. Interface
Es la clase principal del ejecutable Xenon.main.jar, por ello contiene una función
main. Dene una ventana que contiene un JPanel con un CardLayout, que permite
alternar entre las vistas de desarrollo y depuración dentro de una misma ventana. La
gura 23 muestra un diagrama de la clase. El punto de partida del programa es el
método main(), que crea una instancia de la clase Interface. El constructor de Interface
a su vez llama al método addComponentToPane().
Interface dene la clase SliderListener, que tiene como objeto actualizar la frecuencia de ejecución del computador cuando el usuario mueve el deslizador que marca la
56
Figura 23: Diagrama de la clase Interface
frecuencia en la vista de depuración.
Los atributos de la clase Interface son:
JPanel cardPanel. Panel que usa un layout de tipo CardLayout para poder cambiar entre la vista de depuración y de código.
String state. Variable que informa de si estamos actualmente en la vista de código
o de depuración.
JTree projectsTree. Árbol de proyectos, muestra los proyectos y los archivos contenidos en cada proyecto.
TabsManager tabsManager. Gestor de pestañas. Cada pestaña permite visualizar
un archivo que pertenece a alguno de los proyecto abiertos.
DebugViewManager debugViewManager. Controlador principal de la vista de depuración.
JTextArea problemasArea. Área que informa de problemas en la vista de desarrollo, como por ejemplo problemas de compilación.
ProjectsManager projectsManager. Clase gestora de los proyectos abiertos.
JSlider slider. Slider que sirve para cambiar la frecuencia de ejecución del computador.
Los métodos que dene la clase Interface son:
main(). Lanza la aplicación, creando una instancia de Interface.
57
Interface(). Dene la posición de la ventana en pantalla, asigna el título de la
ventana y llama al método addComponentToPane().
addComponentToPane() se encarga de inicializar los atributos de Interface, instanciando por ejemplo el gestor de la vista de depuración y el gestor del árbol
de proyectos y de las pestañas de la vista de desarrollo. Este método se encarga
no solo de inicializar los atributos de la clase sino de dar contenido a la ventana,
añadiendo los menús, las barras de herramientas y demás objetos que se pueden
ver en las vistas de desarrollo y depuración.
6.2.2. ProjectsManager
Figura 24: Diagrama de la clase ProjectsManager
La vista de desarrollo contiene un árbol de proyectos. En ese árbol se muestran los
proyectos abiertos, y en un nivel del árbol inferior, los archivos contenidos en dichos
proyectos. La clase ProjectsManager gestiona dicho árbol de proyectos, y una instancia
de esta clase es asignada al atributo projectsManager de la clase Interface. La gura 24
muestra un diagrama de esta clase.
Esta clase contiene una serie de atributos:
ArrayList<Project> projectsList. Lista de proyectos abiertos.
Project currentlySelectedProject. Proyecto seleccionado actualmente. Esta información es útil para realizar acciones como cerrar proyecto o para compilar.
58
ProjectFile currentlySelectedFileInTree. Fichero actualmente seleccionado en el
árbol de proyectos. Este atributo es usado en acciones como depurar, compilar,
emular, o guardar o cerrar archivo.
JTree projectsTree. Es el árbol de proyectos, es el objeto que es mostrado en
pantalla.
TabsManager tabsManager. Gestor de pestañas. Es necesario por ejemplo para
poder todas las pestañas relacionadas con el proyecto al ejecutar la acción cerrar
proyecto.
Respecto de los métodos de la clase ProjectsManager:
En el constructor se inicializan todos los atributos de la clase. Los métodos getProjectsTree(), getCurrentlySelectedProject(), y getCurrentlySelectedFileInJTree()
son métodos get que devuelven los atributos de la clase correspondientes.
Los métodos mouseClicked(), mouseEntered(), mouseExited(), mousePressed(), y
mouseReleased() implementan la interfaz MouseListener. Concretamente usaremos mousePressed() de forma que un click con el ratón seleccione un proyecto o
archivo en el árbol de proyectos, y un doble click abra el chero clickeado.
El método closeProject() elimina el proyecto actualmente seleccionado del árbol
de proyectos, a la vez que cierra las pestañas abiertas relacionadas con dicho
proyecto.
El método removeFileFromJTree() elimina un chero, que es parámetro de entrada
de dicho método, del árbol de proyectos. Este método es llamado por el gestor de
pestañas cuando
addBinaryFromCode() es usado para añadir un chero binario al árbol de proyectos que tenga el mismo nombre que un chero de código ensamblador, pero con
la extensión ls2.
createProject() muestra un diálogo para elegir el nombre y ubicación del proyecto
a crear, y después lo crea, añadiendo un chero de código ensamblador al mismo.
openProject() abre un proyecto situado en el directorio que el parámetro de entrada contiene.
59
6.2.3. TabsManager
Figura 25: Diagrama de la clase TabsManager
Esta clase permite gestionar el conjunto de archivos abiertos para su edición, los
cuales se muestran en pestañas en la vista de desarrollo. Contiene un solo atributo
privado, tabbedFilePane, que es el panel con todas las pestañas. La gura 25 muestra
un diagrama de esta clase. Los métodos de esta clase son:
getTabbedPane(). Devuelve el panel de pestañas, el atributo tabbedFilePane.
TabsManager(JTabbedPane tab). Constructor, inicializa el atributo tabbedFilePane de la clase.
searchTab(ProjectFile ple). Busca una pestaña que contenga el chero ple.
dontAskAndRemoveTab(Tab t). Elimina la pestaña sin preguntar si quieres guardar el chero.
askAndRemoveTab(Tab t). Si el chero ha sido modicado, pregunta si quieres
guardarlo. Entonces lo cierra.
removeTab(ButtonTabComponent ct). Elimina una pestaña a partir de su etiqueta ButtonTabComponent, que contiene el nombre del archivo y el botón en forma
de X que sirve para cerrarla.
60
addTab(ProjectFile ple) Este método añadirá una pestaña al panel de pestañas
si no existe una pestaña con el chero ple. En otro caso seleccionará y mostrará
dicha pestaña.
saveTabTo(Tab t, String path). Guarda el chero de una pestaña t en la ruta
path.
saveCurrentlySelectedTab(). Guarda el chero de la pestaña actualmente seleccionado.
getCurrentlySelectedTab(). Devuelve la pestaña actualmente seleccionada, o null
si no existe ninguna pestaña.
saveCurrentlySelectedTabAs(). Crea un diálogo que pregunta dónde se quiere
guardar el texto de la actual pestaña, y lo guarda.
saveAllTabs(). Guarda los cambios realizados en los cheros de todas las pestañas.
saveIfModied(ProjectFile codeToDebug). Comprueba si el chero ha sido modicado y pregunta al usuario si quiere guardar los cambios.
closeAllTabsOfProject(Project p). Cierra todas las pestañas del proyecto p.
closeCurrentlySelectedTab(). Cierra la pestaña actualmente seleccionada.
closeAllTabs(). Cierra todas las pestañas, preguntando si guardar cambios en
aquellos cheros que se han modicado.
6.2.4. DebugViewManager
Clase gestora de la vista de depuración. Esta clase realiza todas las tareas de la
interfaz gráca de la vista de depuración, además de lidiar con la clase VirtualComputer.
La gura 26 muestra un diagrama de esta clase. En esta clase se denen otras subclases
y enumeraciones:
Base es una enumeración que indica la base de representación numérica de los
registros y de la memoria principal del computador.
InputType es una enumeración que indica si el computador está pidiendo un
carácter o número como dato de entrada o no está pidiendo datos.
61
Figura 26: Diagrama de la clase DebugViewManager
62
La clase Trace permite crear una traza de la ejecución de un programa. Escribe en
un chero traza.txt en el directorio del proyecto el resultado de cada operación
realizada: el valor de los registros del computador, la dirección de la operación y
la operación.
ExecuteInstructionTask es una clase que extiende la clase TimerTask. En DebugViewManager, una instancia de este clase es usada para llamar de forma periódica
al computador virtual para que ejecute la siguiente instrucción.
TableListener. Clase que escucha cuándo se selecciona una nueva posición de
memoria. Cuando el usuario seleccione una posición de memoria en la tabla, el
registro P cambiará su valor.
ConsoleKeyListener. Clase que escucha la entrada del teclado y la representa
en la consola, e implementa la interfaz KeyListener. Cuando el usuario presione
ENTER, los datos se mandarán al computador.
ColorCellRenderer. Esta clase sirve para resaltar las posiciones de memoria que
cambian en la JTable correspondiente.
FlashySignal. Versión de JLabel que sirve para marcar cuándo se usan las señales
del computador.
FlashyTextField. Versión de JTextField que marca en rojo cuando un registro es
actualizado.
Atributos de la clase:
JTextPane consolaPane. Es la consola de entrada y salida de datos.
ConsoleKeyListener consolaListener. Listener que recoge y trata la entrada proveniente del teclado.
String inputBuer. Buer de entrada. Se van añadiendo datos hasta recibir un
enter (en el caso de que el computador esté pidiendo datos).
long period. Período de reloj de una instrucción del computador en milisegundos,
1000/f(Hz).
int runTo. En el caso de "Ejecutar Hasta", dirección de memoria en la que parar
la ejecución.
63
ColorCellRenderer pTableRenderer, memoriaTableRenderer. Renderers de las tablas pTable y memoriaTable.
Timer instructionTimer. Timer usado para organizar la ejecución de instrucciones
en modo runMode.
Timer changesTimer. Timer usado para los cambios de registro.
ExecuteInstructionTask instructionTask. Tarea de ejecución de una instrucción.
Base base. Variable que contiene la base que actualmente se usa para representar
datos.
VirtualComputer computer. Instancia del computador que se está emulando.
Los métodos de la clase son:
setPidiendoDatos(InputType b). Método que sirve para dar a conocer a la vista
de depuración si el computador está a la espera de datos.
setRegistersBase(Base b). Método que cambia la base en que se muestran los
datos.
setExecutionPeriod(long millisecs). Método que cambia el período de ejecución.
Este cambio de período se notará la siguiente vez que se ejecute el código en modo
"Ejecutar todo" o "Ejecutar hasta".
getConsoleInput(). Devuelve los datos del buer de entrada del teclado.
addConsoleOutput(String text). Añade el texto del parámetro text a la consola.
selectNextInstructionInMemoryNearP(int p). Centra la tabla pTable en la posición indicada por el parámetro de entrada p.
actionRun(). Acción "Ejecutar Todo". Ejecuta las instrucciones del ordenador
hasta llegar a un ALT, con la frecuencia del computador seleccionada.
actionRunTo(int num). Acción "Ejecutar Todo". Ejecuta las instrucciones del
ordenador hasta llegar a cierta instrucción, * o a un ALT, con la frecuencia del
computador seleccionada.
actionPause(). Acción Pausar. Detiene la ejecución de instrucciones.
64
actionRestart(). Acción Reiniciar. Reinicia el estado del computador.
actionExecuteNextInstruction(). Acción Ejecutar siguiente instrucción. Solo ejecuta una instrucción.
changeMemoryAddress(Instruction i). Cuando cierta posición de memoria cambia,
este método es llamado para actualizar la la adecuada de tabla de memoria de
la interfaz gráca.
updateJTableModel(). Cuando muchas posiciones de memoria cambian, este método es llamado para actualizar la tabla de memorian entera de la interfaz gráca.
setDebugCode(ArrayList<Instruction> codeArray, File le). Inicializa la memoria del computador con cierto código.
DebugViewManager(). Constructor de la vista depuración.
Los siguientes métodos son implementaciones de la interfaz VirtualComputer.VirtualComputerListener
que es el Listener del computador:
writeNumberToScreen(). Este método es llamado cuandoquiera que el computador quiera escribir números en pantalla.
stateChanged(). Este método es llamado cuandoquiera que el estado del computador cambie.
addZeros(String s, int a). Añade ceros a la cadena 's' hasta que dicha cadena
tenga una longitud 'a'.
memoryChanged(Instruction i). Este método será llamado cuando el contenido
de la dirección de memoria i cambie.
writeCharacterToScreen(). Este método será llamado cuandoquiera que el computador quiera escribir un carácter en pantalla.
6.2.5. Sobre
Esta clase implementa una ventana popup que muestra información sobre el autor
del proyecto, así como del profesor tutor del mismo. Esta clase es muy simple, y consta
de un constructor y de un método. En el constructor se pasan dos parámetros, que son
la posición x e y en la pantalla. A su vez, el método actionPerformed(ActionEvent e)
sirve para cerrar el popup. La gura 27 muestra un diagrama de esta clase.
65
Figura 27: Diagrama de la clase Sobre
6.2.6. Emulator
Figura 28: Diagrama de la clase Emulator
Es la clase principal del ejecutable Xenon.emu.jar, por ello contiene una función
main. Esta clase es la principal de la vista de emulación. La vista de emulación es
accesible tanto desde la vista de desarrollo del ejecutable xenon.main.jar como desde el
ejecutable xenon.emu.jar de forma standalone. Esta clase realiza todas las tareas de la
interfaz gráca de la vista de emulación, además de lidiar con la clase VirtualComputer,
que es la que ejecuta cada instrucción del computador. A nivel de código, es una versión
más sencilla que el DebugViewManager, pues el usuario no visualiza los registros ni
las posiciones de memoria ni tiene un control de la ejecución como en el modo de
depuración. La gura 28 muestra un diagrama de esta clase.
Esta clase dene una serie de subclases:
ExecuteInstructionTask es una clase que extiende la clase TimerTask. Una instancia de este clase es usada para llamar de forma periódica al computador virtual
66
para que ejecute la siguiente instrucción.
ConsoleKeyListener. Clase que escucha la entrada del teclado y la representa
en la consola, e implementa la interfaz KeyListener. Cuando el usuario presione
ENTER, los datos se mandarán al computador.
BinaryFilter. Sirve de ltro para mostrar solo los cheros con la extensión binaria
"ece". A diferencia del DebugViewManager, que permite depurar tanto código binario como código ensamblador, el emulador solo permite ejecutar código binario.
Atributos de la clase:
JTextPane consoleArea. Es la consola de entrada y salida de datos.
ConsoleKeyListener consolaListener. Listener que recoge y trata la entrada proveniente del teclado.
String inputBuer. Buer de entrada. Se van añadiendo datos hasta recibir un
enter (en el caso de que el computador esté pidiendo datos).
long period. Período de reloj de una instrucción del computador en milisegundos,
1000/f(Hz).
Timer timer. Timer usado para organizar la ejecución de instrucciones.
ExecuteInstructionTask task. Tarea de ejecución de una instrucción.
VirtualComputer computer. Instancia del computador que se está emulando.
boolean exitOnClose. Si el emulador se está ejecutando en forma standalone,
cerrar la ventana cerrará todoel programa, en ese caso esta variable será true.
Los métodos de la clase son:
ˆ getConsoleInput(). Devuelve los datos del buer de entrada del teclado.
setMyTitle(String s). Método que cambia el título de la ventana del emulador.
Sirve para añadir al título del emulador el archivo abierto.
Emulator(). Es el constructor que inicializa la clase. Inicializa los atributos de
la clase, luego llama a addComponentToPane(), que añade todos los elementos
grácos necesarios a la ventana, incluyendo el menú, la barra de herramientas y la
consola. addComponentToPane(Container pane). Añade todos los componentes
visuales necesarios al panel.
67
addConsoleOutput(String text). Añade el texto del parámetro text a la consola.
setPidiendoDatos(InputType b). Método que sirve para dar a conocer a la vista
de depuración si el computador está a la espera de datos.
actionExecuteNextInstruction(). Acción Ejecutar siguiente instrucción. Solo ejecuta una instrucción.
actionPause(). Acción Pausar. Detiene la ejecución de instrucciones.
setRunCode(ArrayList<Instruction> codeArray). Inicializa la memoria del computador con cierto código.
actionRestart(). Acción Reiniciar. Reinicia el estado del computador.
actionRun(). Acción "Ejecutar Todo". Ejecuta las instrucciones del ordenador
hasta llegar a un ALT, con la frecuencia del computador seleccionada.
Los siguientes métodos son implementaciones de la interfaz VirtualComputer.VirtualComputerListener
que es el Listener del computador:
writeNumberToScreen(). Este método es llamado cuandoquiera que el computador quiera escribir números en pantalla.
stateChanged(). Este método es llamado cuandoquiera que el estado del computador cambie.
addZeros(String s, int a). Añade ceros a la cadena 's' hasta que dicha cadena
tenga una longitud 'a'.
memoryChanged(Instruction i). Este método será llamado cuando el contenido
de la dirección de memoria i cambie.
writeCharacterToScreen(). Este método será llamado cuandoquiera que el computador quiera escribir un carácter en pantalla.
68
6.2.7. VirtualComputer
Figura 29: Diagrama de la clase VirtualComputer
Es una abstracción del funcionamiento del computador Xenon. El emulador y el
depurador usan una instancia de esta clase para ejecutar cada instrucción. Esta clase
mantiene la memoria principal del computador, así como el valor de sus registros. Cuando se ejecuta una instrucción, los registros y la memoria principal cambian de acuerdo
con el funcionamiento denido para el computador. La gura 29 muestra un diagrama
de esta clase. En VirtualComputer se denen una serie de clases y enumeraciones:
69
VirtualComputerListener. Listener del computador, sirve para avisar de que el
computador ha cambiado de estado, o de que el computador quiere escribir en
pantalla.
ComputerSignal. Enumeración de las señales del computador.
ComputerRegister. Enumeración de los registros del computador.
ComputerState. Clase que dene el estado del computador, a nivel de registros
y señales del mismo. Contiene un listener del computador virtual, el valor de los
registros, un mapa que contiene qué registros han cambiado y otro que contiene
qué señales se han activado.
Los atributos de la clase son:
Instruction[] memoryMap. Mapa de memoria del computador.
Instruction[] InitialMemoryMap. Mapa de memoria inicial del computador. Este
dato se guarda para poder retornar el computador al estado inicial.
ComputerState state. Estado del computador.
boolean tracLight. Semáforo que asegura una ejecución ordenada.
En cuanto a los métodos de la clase:
VirtualComputer(). Constructor del computador, inicializa variables.
VirtualComputer(ArrayList<Instruction> memory). Constructor del computador
que inicializa la memoria con el parámetro de entrada 'memory'.
restart(). Lleva el ordenador al estado inicial. Pone a cero los registros y las señales,
y devuelve la memoria principal a su estado inicial.
setListener(VirtualComputerListener l). Asigna un nuevo listener al computador.
getListener(). Devuelve el listener del computador.
setMemoryMap(ArrayList<Instruction> memory). Modica la memoria del computador con el parámetro 'memory'.
setMemoryMapToZero(). Inicializa a cero la memoria del computador.
70
getMemoryMap(). Devuelve el mapa de memoria del computador.
getIndirectAddress(int d). Devuelve M(D), la dirección de memoria contenida en
la posición D.
getNextInstruction(). Devuelve la próxima instrucción a ejecutar, posición que
marca el registro P.
executeNextInstruction(). Método que ejecuta la siguiente instrucción. Este método solo se ejecutará si el semáforo tracLight es false, y la ejecución del método
asigna true al semáforo. De este modo se impide en todo caso la ejecución de este
método de forma concurrente.
6.2.8. ButtonTabComponent
Figura 30: Diagrama de la clase ButtonTabComponent
Esta clase es usada por cada pestaña, en la vista de desarrollo. Permite mostrar
el nombre del archivo de una pestaña, así como un botón con una X que sirve para
cerrar dicha pestaña. En ButtonTabComponent se dene la clase TabButton, que crea
un botón con una x que cierra la pestaña. La gura 30 muestra un diagrama de esta
clase.
ButtonTabComponent contiene tres atributos:
TabsManager manager. Es necesario conocer este dato para poder llamar al método del gestor de pestañas con el n de cerrar la pestaña al presionar el botón
x.
JLabel label. Etiqueta con el nombre del archivo de la pestaña.
71
MouseListener buttonMouseListener. Es una implementación de un MouseAdapter que cierra la pestaña cuando se hace click en el botón x, además de resaltar
dicho botón cuando el ratón pasa por encima.
Los dos métodos de la clase ButtonTabComponent son getLabel(), que devuelve el valor
de la etiqueta de la pestaña que contiene el nombre del archivo abierto; y el constructor
de la clase, que inicializa las variables, añadiendo la etiqueta con el nombre del archivo
de la pestaña, y el botón x de cerrar pestaña.
6.2.9. XenonHelper
Figura 31: Diagrama de la clase XenonHelper
En esta clase se encuentran métodos que permiten compilar código ensamblador,
así como la lectura e interpretación de código binario. Esta clase no contiene ningún
atributo y todos sus métodos son estáticos. La gura 31 muestra un diagrama de esta
clase. En esta clase se denen:
La enumeración PseudoInstruction. Enumera las pseudoinstrucciones válidas en
lenguaje ensamblador.
Los métodos de la clase son:
generateMemoryMap(ArrayList<Instruction> in). Este método recoge la salida
del método translateToInstructions(String) y lo convierte en un mapa de memoria.
72
ArrayList<Instruction> translateToInstructions(String code). Lee una cadena de
texto y la traduce a instrucciones. Es el método principal en la compilación de
código ensamblador a código binario.
searchLabel(ArrayList<LineCode> lineCodeArray, String addressLabel). Busca
etiqueta en una lista de líneas de código.
translateToBinary(ArrayList<Instruction> code). Traduce a binario un programa, una vez tenemos las instrucciones que lo forman. Este es el principal método
que permite guardar en formato ece el código binario de un programa.
intToByte(int i). Método usado para convertir de int a byte.
byteToInt(byte b). Método usado para convertir de byte a int.
translateFromBinary(byte[] binary). Traduce código binario a un mapa de memoria que contiene un programa. Es el método principal a la hora de leer código
binario y traducirlo a instrucciones que entienda el computador virtual Xenon.
openBinaryFile(File le). Abre un chero binario y devuelve el mapa de instrucciones, haciendo uso del método translateFromBinary(byte[] binary).
saveToBinaryFile(File le, ArrayList<Instruction> ins) . Guarda el código binario de un programa en formato "ece", para ello hace uso de translateToBinary(ArrayList<Instruction> code).
6.2.10. LineCode
Figura 32: Diagrama de la clase LineCode
La clase LineCode. Contiene la información de una línea de texto del código ensamblador. Es una clase intermediaria usada en la compilación del código ensamblador.
73
Contiene información como: la instrucción a la que se traduce la línea de código, el
número de línea, la pseudoInstrucción a la que se reere la línea de código, y etiqueta
(en formato texto) usada en dicha línea de código ensamblador. La gura 32 muestra
un diagrama de esta clase.
6.2.11. Instruction
Figura 33: Diagrama de la clase Instruction
La clase Instruction dene una instrucción, así como una serie de métodos para
manejar dicha instrucción. Una instancia de esta clase contendrá toda la información
de una instrucción: la posición de memoria en que se encuentra, el código de operación
y el operador de la instrucción. La gura 33 muestra un diagrama de esta clase.
Instruction contiene la enumeración OperationCode, que enumera todos los códigos de operación posibles. Aquí, en código de operación se incluye tanto el código de
operación como el modo de direccionamiento, de forma que si por ejemplo el código de
operación es SUM y el modo de direccionamiento es directo, el OperationCode es SUM;
74
y si es indirecto el OperationCode es SUMI.
Los atributos que contiene un objeto de la clase Instruction son:
OperationCode operationCode. Código de operación de la instrucción, e incluye
el modo de direccionamiento.
int insOperator. Operador de la instrucción (normalmente será una dirección de
memoria.
int data. Dato sin signo de 16 bit, correspondiente a la instrucción tal y como se
guarda en binario, pero en formato decimal. Contendrá un valor entre 0 y 65535.
Los números negativos se guardarán en complemento a 2 de 16bit.
int addressLocation. Posición de memoria en que se encuentra la instrucción,
tendrá un valor entre 0 y 2048 puesto que el direccionamiento es de 11 bits. Si no
se ha denido, la posición de memoria será -1.
Los métodos de la clase son:
Instruction(). Constructor que incializa todo a cero.
Instruction(OperationCode oc, int operator). Constructor que inicializa el contenido de la instrucción (código+operador), pero no dene la posición de memoria
en que se encuentra la instrucción.
setInstruction(OperationCode oc, int operator). Método que inicializa el contenido de la instrucción (código+operador), pero no dene la posición de memoria en
que se encuentra la instrucción.
setAddressLocation(int ma). Sitúa la instrucción en la posición de memoria 'ma'.
getAddressLocation(). Devuelve la posición de memoria de la instrucción.
setOperationCode(OperationCode oc). Método que cambia el código de operación
de la instrucción.
setInstructionOperator(int operator). Método que cambia el operador de la instrucción.
setInstructionSigned(int d). Toma como entrada el dato (con signo) que corresponde a la instrucción. El parámetro d debe pertenecer a [-32768, 32767] o lanzará
una excepción
75
setInstructionUnsigned(int d). Toma como entrada el dato (sin signo) que corresponde a la instrucción. El parámetro d debe pertenecer a [0, 65535] o lanzará una
excepción.
getOperationCode(). Devuelve el código de operación de la instrucción.
getInstructionOperator(). Devuelve el operador de la instrucción (en general será
una dirección de memoria).
getDataUnsigned(). Devuelve el dato guardado en memoria, sin signo, con un
valor entre 0 y 65535.
getDataSigned(). Devuelve el dato guardado en memoria, sin signo, con un valor
entre 32768 y 32767.
updateFromData(). Calcula qué código de operación y operador tiene la instrucción a partir del dato guardado en memoria.
updateFromInstruction(). Calcula el dato a guardar en memoria, a partir del
código de operación y la dirección en memoria.
toString(). Crea una cadena que representa la instrucción.
6.2.12. PopupListener
Figura 34: Diagrama de la clase PopupListener
Esta clase extiende la clase MouseAdapter e implementa un listener que muestra un
popup cuando se hace click derecho con el ratón en cierto objeto. Como atributo tiene
JPopupMenu popup, que dene el popup a mostrar y es un parámetro que se pasa en el
constructor de la clase. Los demás métodos denidos sirven para mostrar dicho popup.
La gura 34 muestra un diagrama de esta clase.
76
Figura 35: Diagrama de la clase Project
6.2.13. Project
La clase Project dene un proyecto y sus propiedades básicas. Los únicos métodos
denidos en esta clase son el constructor, que inicializa los atributos de la clase, y el
método toString(), que da el nombre del chero en formato cadena. La gura 35 muestra
un diagrama de esta clase. Los atributos de la clase son:
File le. Contiene el directorio donde está localizado el proyecto.
ArrayList <ProjectFile> projectFiles. Lista de cheros pertenecientes al proyecto.
DefaultMutableTreeNode pnode. Nodo del proyecto en el árbol de proyectos.
6.2.14. ProjectFile
Figura 36: Diagrama de la clase ProjectFile
Dene un chero perteneciente a un proyecto. Esta clase dene la enumeración
FileType, que enumera los tipos de archivo que un chero de un proyecto puede ser:
código binario, código ensamblador, o texto. La gura 36 muestra un diagrama de esta
clase.
A su vez, un objeto de la clase ProjectFile contendrá los siguientes atributos:
DefaultMutableTreeNode fnode. Nodo de este chero en el árbol de proyectos.
FileType type. Dene el tipo de chero.
77
File le. Ruta del chero en el sistema de archivos.
Project project. Proyecto al que pertenece el chero
Los métodos de esta clase:
ProjectFile(File f, Project p). Constructor, inicializa los atributos de la clase. Las
extensiones reconocidas para los cheros de un proyecto son ls2 (código) y ece
(binario). El resto de archivos es tratado como texto.
toString(). Devuelve el nombre del chero en una cadena.
setNode(DefaultMutableTreeNode no). Asigna 'no' como nodo de este chero en
el árbol de proyectos.
6.2.15. Tab
Figura 37: Diagrama de la clase Tab
Implementa una pestaña que muestra un archivo, en la vista de desarrollo. Una pestaña mostrará un archivo, que pertenecerá a un proyecto abierto. La gura 37 muestra
un diagrama de esta clase. Los atributos que un objeto de esta clase contendrá son:
ProjectFile pFile. Fichero que contiene la pestaña.
JTextArea textArea. Área de texto de la pestaña.
JLabel label. Etiqueta de la pestaña
boolean isModied. Indica si el texto ha sido modicado y todavía no se ha
guardado.
78
Esta clase implementa una interfaz KeyListener, de forma que cuando el texto de la pestaña, la pestaña quede marcada mostrando que las modicaciones del archivo realizadas
por el usuario no han sido guardadas todavía. Es por ello que se han añadido los métodos keyPressed(KeyEvent arg0) , keyReleased(KeyEvent arg0), y keyTyped(KeyEvent
arg0).
Los demás métodos de esta clase son:
setLabel(JLabel l). Modica la etiqueta de la pestaña.
isModied(). Indica si hay cambios no guardados del chero.
setModied(boolean b). Marca el chero como modicado/no modicado.
Tab(JTextArea ta, ProjectFile pf). Constructor que inicializa los atributos del
objeto.
6.2.16. JConnector
Figura 38: Diagrama de la clase JConnector
Clase principal del conector que conecta dos objetos con echas. El constructor tiene
como parámetros los dos objetos JComponent a conectar mediante echas, el tipo de
línea que los conecta y el color. La gura 38 muestra un diagrama de esta clase.
79
6.2.17. ConnectorContainer
Figura 39: Diagrama de la clase ConnectorContainer
Extensión de JPanel que permite añadir conectores con echas entre objetos contenidos en dicho JPanel. El panel que contiene el dibujo del computador digital en la
vista de depuración ha de ser de esta clase para poder pintar las echas que conectan
los diferentes elementos del computador, como los registros, la memoria, los buses o las
señales de control. La gura 39 muestra un diagrama de esta clase.
Contiene un atributo, ArrayList<JConnector> connectors, donde se guardan todos
los conectores. A su vez dene los siguientes métodos:
ConnectorContainer(). Constructor de la clase, inicializa el atributo connectors.
addConnector(JConnector c). Añade un conector al panel.
addConnectors(ArrayList<JConnector> c). Añade una lista de conectores al panel.
getConnectors(). Devuelve los conectores del panel.
paint(Graphics g). Pinta los conectores del panel.
80
6.2.18. ConnectLine
Figura 40: Diagrama de la clase ConnectLine
Dene una línea usada por un JConnector. Es la clase que se encarga de pintar la
línea de acuerdo a los parámetros establecidos, como por ejemplo el color, grosor de la
línea y los extremos con echa. La gura 40 muestra un diagrama de esta clase.
81
82
7. Manual de usuario
El programa tiene 3 vistas principales:
Vista de desarrollo: En esta vista se desarrolla el código ensamblador del computador. Desde esta vista se tiene acceso a las vistas de depuración y de emulación.
Vista de depuración: En esta vista se controla la ejecución del programa ensamblador, teniendo acceso a los registros del computador y las posiciones de memoria.
Esta vista solo es accesible desde la vista de desarrollo.
Vista de emulación: En esta vista se ejecuta la emulación del computador, representándose en la consola la entrada y salida de datos del computador. Esta vista
es accesible desde la vista de desarrollo y también se puede ejecutar de forma
autónoma.
7.1. Ejecución
Existen dos ejecutables, el entorno de desarrollo y el emulador. Los ejecutables java
son:
xenon.main.jar
xenon.emu.jar
Para ejecutarlos desde Linux, Mac o Windows, se pueden ejecutar desde la línea de
comandos:
$ java -jar xenon.main.jar
$ java -jar xenon.emu.jar
Otra opción en Linux es ejecutar los scriptsGite, Vivek (1999) main.sh y emu.sh.
En multitud de versiones de windows basta con hacer doble click sobre los archivos jar
para que estos se ejecuten.
7.2. Vista de desarrollo
Al iniciar el ejecutable xenon.main.jar, el programa muestra la vista de desarrollo.
Desde esta vista el usuario es capaz de desarrollar el código ensamblador, depurarlo,
así como entrar en el emulador. La vista cuenta con una barra de menú, una barra de
herramientas, un árbol de proyectos, una zona de edición y un cuadro de información.
83
La mayoría de acciones posibles están disponibles tanto desde la barra de herramientas
como desde la barra de menú. La gura 41 muestra la vista que el programa presenta
al iniciar el programa:
Figura 41: Vista inicial de desarrollo.
En la vista de la gura 42 se puede observar un escenario típico en donde se han
abierto diversos proyectos, con un archivo de código abierto.
84
Figura 42: Ejemplo de desarrollo
Figura 43: Barra de herramientas
La gura 43 muestra la barra de herramientas. Desde la barra de herramientas se
tiene acceso a diversas acciones comunes:
Nuevo chero. Crea un nuevo chero dentro del proyecto que esté seleccionado.
Guardar. Guarda el chero seleccionado.
Guardar como... Guarda el chero seleccionado con un nuevo nombre.
Guardar todo. Guarda todos los cheros modicados.
Abrir proyecto.
Cerrar proyecto.
85
Compilar. Compila el chero de código fuente seleccionado. En caso de no haber
seleccionado un chero con código fuente, compila el archivo de código fuente del
proyecto al que pertenece el chero seleccionado.
Depurar. Abre la vista de depuración con las instrucciones del chero de código
fuente o binario seleccionado.
Ejecutar. Abre la vista de emulación con las instrucciones del chero binario
seleccionado.
Desde la barra de menús también se tiene acceso a todas las acciones. Como se puede
observar en la gura 44, muchas de las acciones cuentan con combinaciones de teclas
de acceso rápido.
Figura 44: Barra de menús de la vista de desarrollo
7.3. Vista de emulación
La vista de emulación permite ejecutar código binario. En esta vista no se puede
controlar la ejecución de un programa, a diferencia de la vista de depuración. Tampoco
se puede visualizar los registros del computador ni los registros de la memoria principal.
El motivo es que uno no puede visualizar de forma directa los registros del computador
digital ni su memoria principal, a menos que el propio programa en ejecución esté
diseñado para hacerlo.
La vista cuenta con una barra de menú, una barra de herramientas que se puede ver
en la gura 46, un árbol de proyectos, una zona de edición y un cuadro de información.
La mayoría de acciones posibles están disponibles tanto desde la barra de herramientas
como desde la barra de menú. La vista de ejecución está disponible tanto desde la vista
de desarrollo como de forma standalone desde el ejecutable xenon.emu.jar.
La gura 45 la vista que el programa presenta al iniciar el programa:
86
Figura 45: Vista de emulación
Figura 46: Barra de herramientas de la vista de emulación
Las acciones disponibles son:
Abrir ejecutable.Abre un ejecutable en formato de código binario de la máquina
Xenon.
Guardar texto de la consola. Guarda el texto mostrado en la consola.
Reiniciar máquina. Reinicia el programa así como el estado de los registros y
memoria principal de la computadora digital, limpiando el texto de la consola.
Salir. Si se está ejecutando el emulador en forma standalone, cierra todo el
programa. Si el emulador se ha abierto desde la vista de desarrollo, solo cierra la
vista de emulación.
Desde la barra de menús también se tiene acceso a todas las acciones. Dicha barra de
menús se presenta en la gura 47.
87
Figura 47: Barra de menús de la vista de emulación
7.4. Vista de depuración
La vista de depuración permite controlar el ujo de ejecución de un programa. Esta
vista es accesible desde la vista de desarrollo, y permite depurar tanto archivos de código
binario como de código ensamblador. Las acciones de control de la ejecución incluyen la
ejecución de una sola instrucción, la ejecución hasta llegar cierta dirección de memoria,
ejecución completa y pausa de la ejecución. Además permite congurar la frecuencia
de proceso de instrucciones del computador digital xenon, así como observar el tiempo
transcurrido en la ejecución del programa.
También contiene una representación del computador digital, junto con sus registros
y señales, así como el contenido de la memoria principal. Tras la ejecución de cada
instrucción, los registros del computador y los registros de memoria que han cambiado
se marcarán en azul. A su vez también se marcarán las señales de gobierno que el
computador ha usado en la ejecución de la instrucción.
El visor entorno a P centrará la visualización de la memoria entorno a la dirección
de la instrucción ejecutada tras su ejecución, mientras que el visor de la memoria de la
parte inferior solo cambiará de posición según el usuario lo elija.
Cuando el usuario hace click en un registro de la memoria principal en el visor de
memoria entorno a P, el registro P cambia a la dirección del registro clickeado, de forma
que esa será la próxima instrucción que se ejecutará.
En la gura 48 se puede ver la vista de depuración en uso:
88
Figura 48: Vista de depuración
Figura 49: Barra de control de de la vista de depuración
La gura 49 muestra la barra de control de de la vista de depuración. Las acciones
que se pueden realizar son:
Ejecutar Instrucción. Ejecuta la siguiente instrucción, que viene dada por el
valor del registro P.
Ejecutar Hasta... Mostrará un diálogo donde el programa pide al usuario la
dirección de memoria hasta la que el usuario quiere ejecutar el programa. Entonces
el programa se ejecutará hasta llegar a una instrucción de parada (ALT) o hasta
llegar a la dirección de memoria indicada.
Comenzar de nuevo. Reinicia tanto los registros del computador como la memoria principal.
Ejecutar todo. Ejecuta el programa desde la posición de memoria actual indicada por el registro P hasta llegar a una instrucción ALT de parada.
89
Pausar. Pausa la ejecución del programa, en el caso de que el programa se esté
ejecutando.
Salir del modo depuración. Devuelve al usuario a la vista de desarrollo.
Salir. Accesible desde el menú Archivo>Salir. Cierra el programa.
Elegir base. Haciendo uso del menú, se llega a Vista>Base, desde donde se puede
elegir la base de representación de los registros del computador y de la memoria
principal. Las opciones son Binario, Decimal, y Hexadecimal.
Cambiar la frecuencia del reloj, haciendo uso del slider o deslizador horizontal.
También es importante notar que a la izquierda del deslizador de frecuencia se muestra el
tiempo de ejecución del programa, que se actualiza tras la ejecución de cada instrucción.
Desde la barra de menús, mostrada en la gura 50, también se tiene acceso a todas las
acciones. Como se puede observar, muchas de las acciones cuentan con combinaciones
de teclas de acceso rápido.
Figura 50: Barra de menús de la vista de depuración
90
8. Posibles ampliaciones
En este capítulo analizamos una serie de posibles ampliaciones del presente proyecto
que, si bien su implementación no entra dentro del ámbito del proyecto, si puede resultar
interesante a la hora de continuar con el trabajo del emulador. Las ampliaciones que se
proponen son:
Una interfaz gráca para plataformas móviles.
Una ampliación del juego de instrucciones del computador digital.
En lo que sigue se detallan las acciones que habrían de llevarse a cabo a la hora de
implementar dichas ampliaciones.
8.1. Interfaz gráca para plataformas móviles
El código java no funciona directamente en plataformas móviles, pues el bytecode
no es el mismo y la interfaz gráca tampoco. Para realizar una versión del emulador en
plataformas móviles como AndroidMednieks, Zigurd (2012), es necesario reimplementar
la interfaz gráca pero se puede reusar el código referente a la lectura de binarios,
compilación de código ensamblador y emulación del computador.
Es importante recalcar que de hecho la mayor parte del código corresponde a la interfaz gráca, por ello una implementación del emulador del computador virtual Xenon
en otra plataforma, como Android, donde se tenga que rehacer desde cero la interfaz
gráca, no es trivial. El código del programa es reusable, ya que existe una clara separación entre las clases que pertenecen a la interfaz gráca y aquellas que no pertenecen
a ella. De hecho, gracias a esa separación, la vista de emulación y la vista de depuración
usan la misma clase para emular la ejecución de instrucciones del computador virtual
xenon, y para pasar de código binario a código que pueda interpretar el computador
virtual xenon. Dicho de otro modo, la separación entre clases relativas a la interfaz
gráca y clases relativas al funcionamiento abstracto del computador permite que el
código sea reusable, sin embargo es inevitable que la parte de la interfaz gráca tenga
que reescribirse al usarse otra librería gráca.
Las clases que si se pueden reusar son aquellas independientes de la interfaz gráca,
relativas al funcionamiento abstracto del computador digital Xenon:
Instruction. Esta clase dene una instrucción y unos métodos útiles para manejarla. No necesitaría ninguna modicación.
91
XenonHelper. Esta clase dene una serie de métodos que sirven para convertir un
texto en instrucciones que pueda entender el emulador, es decir compilar; y para
guardar y leer un archivo de código binario del computador. Los métodos saveToBinaryFile() y openBinaryFile() es posible que necesiten alguna modicación,
pues acceder al sistema de cheros y leer o guardar un archivo es posible que no
se realice de la forma estándar en plataformas como un móvil Android. Todos los
demás métodos de esta clase son reusables tal cual.
VirtualComputer. Esta clase contiene los registros del computador digital y su
memoria principal y es la que se encarga de ejecutar instrucciones y modicar los
registros, memoria y señales de gobierno que sea necesario para ello. Esta clase
tampoco hace falta que sea modicada, es independiente de la interfaz gráca.
Todas las demás clases del programa son totalmente dependientes de la interfaz gráca
y habrán de ser reimplementadas desde cero haciendo uso de las librerías de interfaz
gráca de Android. Será necesario por tanto reimplementar las tres vistas: emulación,
depuración y desarrollo.
A continuación sigue una breve introducción para el uso de las clases anteriormente
mencionadas de forma que se pueda implementar una nueva interfaz gráca. En los
siguientes ejemplos haremos un uso básico de las clases Instruction, XenonHelper y
VirtualComputer, que son las clases reusables e independientes de la interfaz gráca.
Es decir, una interfaz gráca para Android hará un uso de estas clases similar al que se
muestra en los siguientes ejemplos.
Supongamos que tenemos una cadena de texto correspondiente al código ensamblador, en una variable de tipo String. El contenido de dicha cadna de texto podría ser
algo tan sencillo como ORG 0\n ALT\n FIN. En el ejemplo de la gura 51 queremos
convertir la cadena de texto a un conjunto de instrucciones que el computador virtual
de VirtualComputer pueda entender.
92
String
codigo_ensamblador ;
.
.
.
A r r a y L i s t <I n s t r u c t i o n >
try
program_instructions
=
null ;
{
program_instructions
=
XenonHelper . t r a n s l a t e T o I n s t r u c t i o n s ( t e x t ) ;
}
catch ( E x c e p t i o n
ce )
{
System . o u t . p r i n t l n ( c e . g e t M e s s a g e ( ) ) ;
}
Figura 51: Traducción de texto a instrucciones ensamblador
Una vez tenemos el programa almacenado como un conjunto de instrucciones en la
variable program_instructions, una instancia del computador virtual puede ejecutar dicho programa. Es importante añadir un listener al computador virtual para poder estar
al tanto de los cambios de los registros y señales del computador. En este caso la clase
principal implementará el listener. En este ejemplo solo ejecutamos una instrucción. El
computador inicialmente tendrá el puntero P a cero, luego ejecutaremos la instrucción
que esté en la posición de memoria cero. La gura 52 muestra el código necesario para
ejecutar una instrucción.
93
c l a s s Program implements V i r t u a l C o m p u t e r . V i r t u a l C o m p u t e r L i s t e n e r
public V i r t u a l C o m p u t e r c o m p u t e r ;
public Program ( A r r a y L i s t <I n s t r u c t i o n > p r o g r a m _ i n s t r u c t i o n s ) {
c o m p u t e r = new V i r t u a l C o m p u t e r ( ) ;
c o m p u t e r . s e t L i s t e n e r ( this ) ;
// I n i c i a l i z a m o s
l a memoria d e l
{
computador
c o m p u t e r . setMemoryMap ( c o d e A r r a y ) ;
// E j e c u t a m o s una i n s t r u c c i ó n .
computer . e x e c u t e N e x t I n s t r u c t i o n ( ) ;
}
// Métodos de V i r t u a l C o m p u t e r L i s t e n e r
@Override
public void
writeNumberToScreen ( )
{
}
@Override
public void
stateChanged ( )
{
}
@Override
public void
memoryChanged ( I n s t r u c t i o n
i )
{
}
@Override
public void
writeCharacterToScreen ()
{
}
}
Figura 52: Ejecución de una instrucción
Se puede observar que hemos incluido las implementaciones de la interfaz VirtualComputerListener, si bien dichas implementaciones no hacen nada. Para poder realizar
una interfaz que sea capaz de manejar el computador virtual Xenon, habremos de implementar los métodos de dicha interfaz. Por ejemplo, writeCharacterToScreen() será
llamado cuando el computador quiera mostrar un carácter en pantalla. Y memoryChanged() será llamado cuando durante la ejecución de una instrucción, se modique una
posición de memoria. A su vez el computador llamará a stateChanged() tras la ejecución
de una instrucción, de modo que la interfaz pueda hacer uso del método VirtualComputer::getState() y comprobar qué registros y señales se han usado o activado durante la
ejecución de dicha instrucción. Para un ejemplo sencillo pero más completo de interfaz
gráca, ver el código del emulador, en el archivo fuente Emulator.java. En el código, en
94
la denición de cada método se puede encontrar una explicación más detallada de la
funcionalidad y características de cada método.
8.2. Ampliación del juego de instrucciones del computador
El computador digital que aquí se ha presentado tiene instrucciones con un ancho
de 16 bits, y una capacidad de direccionamiento de 11 bits. Esto deja 5 bits para elegir
el código de operación (y modo de direccionamiento) de cada instrucción, lo cual como
mucho da para 32 instrucciones diferentes, las cuales todas menos una ya han sido
usadas. Y sin embargo existen todavía muchos tipos de operaciones que se podrían
denir para el computador. Para ello sería necesario o bien aumentar el tamaño de
la instrucción, es decir la cantidad de bits por instrucción; o disminuir la capacidad
de direccionamiento, sin embargo la capacidad de direccionamiento no es muy grande
ahora mismo. Por tanto la opción preferible es aumentar el tamaño de la instrucción.
De forma general, los cambios en el código del programa que habría que realizar
para añadir operaciones al computador virtual Xenon aumentando el tamaño de la
instrucción son:
Añadir los códigos de operación a la enumeración de códigos de operación. También será necesario cambiar la constante que dene el número máximo de código
de operación.
Modicar aquellas partes del código que hagan uso de las instrucciones. Por ejemplo, habrá que añadir el comportamiento de las nuevas instrucciones en la clase
VirtualComputer en el método que ejecuta una instrucción.
Modicar aquellas partes del código que hacen uso del tamaño de las instrucciones.
Por ejemplo, los registros del computador así como los registros de la memoria
principal pasarán a tener otro tamaño. A su vez, la clase Instruction hace uso del
tamaño de una instrucción para interpretar correctamente un dato en formato
decimal y pasarlo a binario o viceversa.
Modicar aquellas partes del código que escriben o leen e interpretan código
binario. Ahora mismo una instrucción, o un registro de la memoria principal,
tiene el tamaño de 2 bytes. Si se añade 1 byte mas, hará falta modicar por
ejemplo la clase XenonHelper, que guarda e interpreta archivos binarios.
95
De forma más concreta, si por ejemplo queremos que la capacidad de direccionamiento
sea de 16 bits y que 8 bits pertenezcan al código de operación (incluyendo modo de
direccionamiento), esto permitiría 28 = 256 operaciones diferentes y una capacidad de
direccionamiento de 216 = 65536 direcciones de memoria diferentes, de forma que cada
instrucción contara con 16+8 = 24 bits = 3 bytes.
Los primeros cambios a realizar serán en la clase Instruction, referentes a las constantes se pueden ver en la gura 53.
public
public
public
public
public
static
static
static
static
static
final
final
final
final
final
int
int
int
int
int
Memory_Address_Limit
=
Instruction_Size_Limit
Register_Max_Limit
=
Register_Min_Limit
=
Operation_Code_Max =
65535;
=
16777215;
8388607;
−8388608;
255;
Figura 53: Cambios de constantes de la Clase Instruction
También será necesario añadir los códigos de operación a la enumeración de códigos
de operación, como se muestra en la gura 54.
public
enum
ALT( 0 ,
0) ,
OperationCode
ALM( 1 ,
ESCI ( 6 ,
7) ,
RES ( 1 1 ,
12) ,
LEE ( 7 ,
2) ,
8) ,
RESI ( 1 2 ,
{
ALMI ( 2 ,
LEEI ( 8 ,
3) ,
CAR( 3 ,
9) ,
13) ,
MUL( 1 3 ,
4) ,
SUM( 9 ,
14) ,
CARI ( 4 ,
10) ,
SUMI ( 1 0 ,
MULI ( 1 4 ,
15) ,
20) ,
DIVI ( 1 6 ,
17) ,
MOD( 1 7 ,
18) ,
MODI( 1 8 ,
19) ,
SAL ( 1 9 ,
SALI ( 2 0 ,
21) ,
SAN ( 2 1 ,
22) ,
SANI ( 2 2 ,
23) ,
SAC ( 2 3 ,
24) ,
SACI ( 2 4 ,
25) ,
SAP ( 2 5 ,
26) ,
SAPI ( 2 6 ,
27) ,
ECA( 2 7 ,
28) ,
LCAI ( 3 0 ,
31) ,
LCA( 2 9 ,
30) ,
5) ,
ESC ( 5 ,
6) ,
11) ,
DIV ( 1 5 ,
ECAI ( 2 8 ,
16) ,
29) ,
// Nuevos c ó d i g o s de o p e r a c i ó n :
OP32 ( 3 1 , 3 2 ) ,
OP33 ( 3 2 ,
33) ,
OP34 ( 3 3 ,
34)
;
Figura 54: Cambios en la enumeración OperationCode
La clase Instruction, como se ha explicado en la sección 6.2.11, permite almacenar
una instrucción en un objeto java. Internamente, un objeto Instruction almacena la
instrucción tanto en forma binaria como en forma simbólica (código de operación y
operador). A la hora de actualizar la instrucción que contiene una variable Instruction,
existe tanto la opción de pasar la nueva instrucción en forma binaria como la opción de
pasar el código de operación y el operador.
96
Si por ejemplo realizamos una llamada a Instruction::setInstruction(OperationCode
oc, int operator), estaremos actualizando la instrucción a partir del código de operación y el operador de forma simbólica, sin embargo internamente la instrucción también
ha de ser guardada en formato binario. Para ello, internamente, el método setInstruction(OperationCode oc, int operator), hará una llamada a updateFromInstruction().
Del mismo modo, podremos actualizar la instrucción a partir del número en formato
binario (en realidad en complemento a 2) que se almacenaría en la memoria del computador, realizando una llamada a Instruction::setInstructionOperator(int operator). De
nuevo, internamente la instrucción también ha de ser guardada en formato simbólico
separando el código de operación y el operador. Para ello, internamente, el método
Instruction::setInstructionOperator(int operator) realizará una llamada a updateFromData().
El método updateFromData() devuelve el operador y el operando a partir del dato
de la instrucción (que se guarda en decimal en complemento a 2). Este método es dependiente del tamaño de la instrucción y del código de operación y del direccionamiento,
luego habría que modicarlo tal y como se muestra en la gura 55:
También es necesario hacer cambios en el método updateFromInstruction(), que
actualiza el dato en complemento a 2 a partir del operador y código de operación. Ese
método también depende del formato de un registro de memoria. Dichos cambios se
muestran en la gura 56.
97
private void
{
updateFromData ( )
int c o d e =
i f ( c o d e >=
{
( data
0 &&
&
0 xFF0000 )
int i = − 1;
for ( O p e r a t i o n C o d e
{
>>
16;
c o d e <= Operation_Code_Max )
i f ( code
==
getIndex :
OperationCode . v a l u e s ( ) )
getIndex . code ( ) )
{
i
=
getIndex . index ( ) ;
break ;
}
}
if ( i
!=
−1)
{
operationCode
insOperator
=
isInstruction
=
OperationCode . v a l u e s ( ) [ i ] ;
( data
&
=
true ;
=
false ;
0xFFFF ) ;
}
else
{
isInstruction
}
}
else
{
isInstruction
=
false ;
}
}
Figura 55: Cambios en Instruction::updateFromData()
98
private void
{
updateFromInstruction ()
int f o o = 0 ;
if ( isInstruction ())
{
foo
=
( operationCode . code ( )
<<
16)
|
insOperator ;
}
else
{
i f ( operationCode
==
null
&&
insOperator
!=
−1)
{
foo
=
insOperator ;
}
else i f
( operationCode
!=
null&&
insOperator
==
−1)
{
foo
=
operationCode . code ( )
<<
16;
}
}
try {
setInstructionUnsigned ( foo ) ;
}
catch ( E x c e p t i o n
e)
{
}
}
Figura 56: Cambios en Instruction::updateFromInstruction()
Serían necesarios cambios en la clase VirtualComputer. En el método que ejecuta
la siguiente instrucción, habría que añadir el código que ejecuta las nuevas instrucciones, es decir, que modica registros y hace uso de las señales de gobierno. Como se
puede ver en la gura 57, hay que modicar los registros necesarios, e indicar al estado
del computador aquellos registros y señales que se han usado para la ejecución de la
instrucción:
99
public
ComputerState
// Usamos e l
executeNextInstruction ()
semáforo
trafficLight
throws
// l l a m a d a s en p a r a l e l o / c o n c u r r e n t e s a e s t a
if ( trafficLight
trafficLight
=
// Recogemos l a
Instruction
false )
true ;
==
Exception
p a r a q u e no s e puedan
{
realizar
instrucción .
{
instrucción a ejecutar
ins
= memoryMap [ s t a t e . g e t P ( ) ] ;
// Marcamos t o d o s
los
registros
y s e ñ a l e s como no m o d i f i c a d o s
state . resetSignalsRegisters ();
if ( ins . isInstruction ()
{
==
true )
switch ( i n s . g e t O p e r a t i o n C o d e ( ) )
// E l e g i m o s q u é o p e r a c i ó n
// s e g ú n
el
ejecutar
c ó d i g o de o p e r a c i ó n .
{
case ALT :
break ;
.
.
.
// Nuevas
instrucciones
case OP32 :
try {
int o p e r a t o r
=
ins . getInstructionOperator ( ) ;
memoryMap [ o p e r a t o r ] . s e t I n s t r u c t i o n S i g n e d ( s t a t e . g e t A ( ) ) ;
s t a t e . g e t L i s t e n e r ( ) . memoryChanged ( memoryMap [ o p e r a t o r ] ) ;
s t a t e . setChangedMemory (
memoryMap [ o p e r a t o r ] . g e t A d d r e s s L o c a t i o n ( ) ) ;
s t a t e . s e t T ( s t a t e . getA ( ) ) ;
s t a t e . s e t I ( i n s . getDataSigned ( ) ) ;
state . setS ( operator ) ;
s t a t e . incrementP ( ) ;
// Ahora s e ñ a l a m o s q u é
registros
han cambiado
true ) ;
true ) ;
s t a t e . s e t R e g i s t e r C h a n g e d ( C o m p u t e r R e g i s t e r . S , true ) ;
s t a t e . s e t R e g i s t e r C h a n g e d ( C o m p u t e r R e g i s t e r . P , true ) ;
s t a t e . s e t R e g i s t e r C h a n g e d ( ComputerRegister . T,
s t a t e . setRegisterChanged ( ComputerRegister . I ,
// Aquí mostramos
// e j e c u c i ó n de
las
la
// A l g u n o s
setSignal
// r e p e t i r
llamadas
//M(P)
señales
u s a d a s en
el
t r a n s c u r s o de
instrucción .
los
comento ,
pero
solo
iguales
−> I
true ) ;
true ) ;
s t a t e . s e t S i g n a l ( C o m p u t e r S i g n a l . LECM, true ) ;
s t a t e . s e t S i g n a l ( C o m p u t e r S i g n a l . ST , true ) ;
s t a t e . s e t S i g n a l ( C o m p u t e r S i g n a l . SP ,
s t a t e . s e t S i g n a l ( C o m p u t e r S i g n a l . ES ,
Figura 57: Cambios en VirtualComputer::executeNextInstruction()
100
p a r a no
la
s t a t e . s e t S i g n a l ( C o m p u t e r S i g n a l . EI ,
//A
−> M(D)
s t a t e . s e t S i g n a l ( C o m p u t e r S i g n a l . SD ,
true ) ;
true ) ;
// s t a t e . s e t S i g n a l ( C o m p u t e r S i g n a l . ES ,
true );
true ) ;
s t a t e . s e t S i g n a l ( C o m p u t e r S i g n a l . ET , true ) ;
s t a t e . s e t S i g n a l ( C o m p u t e r S i g n a l . ESCM, true ) ;
s t a t e . s e t S i g n a l ( C o m p u t e r S i g n a l . SA ,
//P
−> P+1
s t a t e . s e t S i g n a l ( C o m p u t e r S i g n a l . INCP ,
true ) ;
state . sendSignals ( ) ;
}
catch ( I n d e x O u t O f B o u n d s E x c e p t i o n
{
throw new
exception )
E x c e p t i o n ( "ALM" ) ;
}
break ;
case OP33 :
. . .
Figura 58: Cambios en VirtualComputer::executeNextInstruction() (continuación)
La clase XenonHelper necesitará cambios. Por ejemplo, a la hora de leer o escribir
un archivo de código binario ahora una instrucción no ocupa dos sino tres bytes. Por
ello habrá que modicar translateToBinary() tal y como se puede observar en la gura
59:
public s t a t i c byte [ ]
{
t r a n s l a t e T o B i n a r y ( A r r a y L i s t <I n s t r u c t i o n >
code )
byte [ ] b i n a r y = new byte [ ( I n s t r u c t i o n . Memory_Address_Limit + 1 ) * 3 ] ;
int f o o = 0 ;
for ( I n s t r u c t i o n i : c o d e )
{
foo
=
i . getDataUnsigned ( ) ;
// BigEndian o r
LittleEndian ?
* 3 ] = intToByte ( f o o
. getAddressLocation ()*3 + 1] =
binary [ i . getAddressLocation ( )
binary [ i
intToByte ( ( f o o
&
0 x00FF00 )
binary [ i . getAddressLocation ()
intToByte ( ( f o o
&
0 x00FF00 )
>>
*3
+
>>
8);
2]
=
16);
}
return
binary ;
}
Figura 59: Cambios en XenonHelper::translateToBinary()
101
&
0 x0000FF ) ;
De igual modo también será necesario modicar translateFromBinary() para tener
en cuenta el mayor tamaño de cada instrucción, según se muestra en el código de la
gura 60:
public s t a t i c
A r r a y L i s t <I n s t r u c t i o n >
{
A r r a y L i s t <I n s t r u c t i o n >
int
foo
=
i
=
new
byte [ ]
binary )
A r r a y L i s t <I n s t r u c t i o n > ( ) ;
0;
Instruction
for ( int
array
translateFromBinary (
sr ;
=
0;
i
<
binary . length /3;
i ++)
{
f o o=
+
byteToInt ( binary [ i
( byteToInt ( binary [ i
i f ( foo
!=
{
sr
=
try {
*3
*3])
+
+
2])
( byteToInt ( binary [ i
<<
16);
0)
new
Instruction ();
sr . setInstructionUnsigned ( foo ) ;
sr . setAddressLocation ( i ) ;
}
catch ( E x c e p t i o n
e)
{
}
a r r a y . add ( s r ) ;
}
}
return
array ;
}
Figura 60: Cambios en XenonHelper::translateFromBinary()
102
*3
+
1])
<<
8)
9. Conclusiones y cumplimiento de objetivos
En este Proyecto Fin de Carrera se ha estudiado un computador digital, creando un
emulador y un entorno de programación simple llamado Xenon que permite el uso de
dicho computador. El programa Xenon permite escribir, compilar, ejecutar y depurar
código ensamblador del computador digital diseñado. Se ha utilizado el lenguaje de
programación Java para la programación del emulador Xenon, ya que un ejecutable
Java se puede ejecutar sin cambio alguno en múltiples plataformas, sin que se concurra
en una gran pérdida de rendimiento.
Se han propuesto dos ampliaciones:
La implementación del programa Xenon para plataformas móviles, como por ejemplo Android. Para ello, sería necesario escribir una nueva interfaz gráca.
Ampliación de las instrucciones que maneja el computador digital. Para ello sería
necesario realizar modicaciones tanto en la parte de la interfaz gráca como la
parte del código relativa al emulador.
En cuanto a los objetivos del proyecto, se puede decir que:
El diseño de la computadora simple se ha cumplido con el presente documento. El
desarrollo del software que permite emular dicho computador, también se ha realizado satisfactoriamente, incluyendo un entorno de programación, un depurador
y un emulador.
En el presente documento se han detallado dos posibles ampliaciones de este
proyecto.
Gracias a una implementación del emulador Xenon en Java, el emulador puede
ser ejecutado tanto en Windows como Mac y Linux sin necesidad de recompilar
el programa.
El software Xenon se usará en el próximo curso para introducir al alumnado el
funcionamiento de un computador digital simple. El entorno de programación y el
emulador permitirán a los alumnos experimentar con el computador como si éste
fuera una realidad física. A su vez, el depurador muestra el funcionamiento interno
del computador, con detalles como qué registros y señales usa cada instrucción
en cada ciclo, y mostrando al alumno el contenido de dichos registros y de la
memoria del computador.
103
Por tanto se concluye que todos los objetivos del proyecto se han cumplido.
104
10. Bibliografía
Referencias
Acosta Rodriguez, José Ángel (2009). Asignatura de informática de ingeniería aeroespacial. http://www.esi2.us.es/ jaar/docencia.htm.
Arahal, Manuel R; Hernández, José Julio; Limón, Daniel (1986).
CESIUS.
http://www.esi2.us.es/ arahal/CESIUS/cesius.html.
Boole, George (1854).
An Investigation of the Laws of Thought on Which are Founded
the Mathematical Theories of Logic and Probabilities.
Gite, Vivek (1999).
Linux Shell Scripting Tutorial.
Macmillan.
http://bash.cyberciti.biz/guide/.
Lapitsky, Stanislav (2007). Jconnector project. http://java-sl.com/connector.html.
Mednieks, Zigurd (2012).
Programming Android: Java Programming for the New Ge-
neration of Mobile Devices.
O'Reilly Media.
Shannon, Claude E. (1937). A symbolic analysis of relay and switching circuits. Master's
thesis, Massachusetts Institute of Technology.
Shannon, Claude E. (1948). A mathematical theory of communication.
Technical Journal,
Bell System
-:.
van Heesch, Dimitri (1997). Announcing: the rst release of doxygen. -.
Varios (2013). Tortoisehg webpage. http://tortoisehg.bitbucket.org/.
von Neumann, John (1945). First draft of a report on the edvac. Technical report,
United States Army Ordenance Department and the University of Pennsylvania.
105
106
11 Anexos
11.1 Código
11.1.1 ButtonTabComponent.java
package xenon;
import
import
import
import
javax.swing.*;
javax.swing.plaf.basic.BasicButtonUI;
java.awt.*;
java.awt.event.*;
/**
* @brief Usado como tabComponent
* @detail Contiene una JLabel para mostrar el texto y un JButton para
* cerrar la pestaña a la que pertenece.
*/
public class ButtonTabComponent extends JPanel {
/**
*
*/
private static final long serialVersionUID = 1L;
@SuppressWarnings("unused")
private TabsManager manager;
private JLabel label;
public JLabel getLabel()
{
return label;
}
public ButtonTabComponent(TabsManager manager, String Name) {
super(new FlowLayout(FlowLayout.LEFT, 0, 0));
if (manager.getTabbedPane() == null) {
throw new NullPointerException("TabbedPane is null");
}
this.manager = manager;
setOpaque(false);
//Hacer que la JLabel muestre los títulos del JTabbedPane
label = new JLabel(Name);
}
add(label);
//Añadir más espacio entre la etiqueta y el botón
label.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 5));
//Botón de la pestaña
JButton button = new TabButton(manager);
add(button);
//Añadir más espacio a la parte superior del componente
setBorder(BorderFactory.createEmptyBorder(2, 0, 0, 0));
/**
*
* @brief Crea botón con X para cerrar pestaña.
*
*/
private class TabButton extends JButton implements ActionListener {
/**
*
*/
private static final long serialVersionUID = 1L;
private TabsManager manager;
public TabButton(TabsManager manager) {
this.manager = manager;
int size = 17;
setPreferredSize(new Dimension(size, size));
setToolTipText("Cerrar esta pestaña");
setUI(new BasicButtonUI());
//Hacerlo transparente
setContentAreaFilled(false);
//No necesitamos que se pueda enfocar
setFocusable(false);
setBorder(BorderFactory.createEtchedBorder());
setBorderPainted(false);
//Usamos el mismo listener para todos los botones
addMouseListener(buttonMouseListener);
setRolloverEnabled(true);
//Cerrar la pestaña adecuada al hacer click en el botón
addActionListener(this);
}
107
public void actionPerformed(ActionEvent e) {
manager.getTabbedPane().indexOfTabComponent(ButtonTabComponent.this);
manager.removeTab(ButtonTabComponent.this);
}
//No necesitamos actualizar la UI en este caso
public void updateUI() {
}
//Pintar la cruz
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g.create();
//Mover la imagen si se presiona
if (getModel().isPressed()) {
g2.translate(1, 1);
}
g2.setStroke(new BasicStroke(2));
g2.setColor(Color.BLACK);
if (getModel().isRollover()) {
g2.setColor(Color.MAGENTA);
}
int delta = 6;
g2.drawLine(delta, delta, getWidth() - delta - 1, getHeight() - delta - 1);
g2.drawLine(getWidth() - delta - 1, delta, delta, getHeight() - delta - 1);
g2.dispose();
}
}
private final static MouseListener buttonMouseListener = new MouseAdapter() {
public void mouseEntered(MouseEvent e) {
Component component = e.getComponent();
if (component instanceof AbstractButton) {
AbstractButton button = (AbstractButton) component;
button.setBorderPainted(true);
}
}
public void mouseExited(MouseEvent e) {
Component component = e.getComponent();
if (component instanceof AbstractButton) {
AbstractButton button = (AbstractButton) component;
button.setBorderPainted(false);
}
}
};
}
108
11.1.2 JConnector.java
package xenon;
import javax.swing.*;
import java.awt.*;
/**
* The class represents pair of components with a connecting line.
*
* <p>Copyright: Copyright (c) 2007</p>
*
* @author Stanislav Lapitsky
* @version 1.0
*/
/**
* @brief Una de las clases usada para pintar flechitas de un lado a otro
* @detail Librería modificada por Félix Robles, código original de Stanislav Lapitsky.
*/
public class JConnector extends JPanel {
/**
*
*/
private static final long serialVersionUID = 1L;
public static final int CONNECT_LINE_TYPE_SIMPLE = 0;
public static final int CONNECT_LINE_TYPE_RECTANGULAR = 1;
protected JComponent source;
protected JComponent dest;
protected ConnectLine line;
protected int lineArrow = ConnectLine.LINE_ARROW_NONE;
protected int lineType = CONNECT_LINE_TYPE_RECTANGULAR;
protected Color lineColor;
/**
* Constructs default connector.
* @param source JComponent
* @param dest JComponent
*/
public JConnector(JComponent source, JComponent dest) {
this(source, dest, ConnectLine.LINE_ARROW_NONE, Color.BLACK);
}
/**
* Constructs a connector with specified arrow and color.
* @param source JComponent
* @param dest JComponent
* @param lineArrow int
* @param lineColor Color
*/
public JConnector(JComponent source, JComponent dest, int lineArrow, Color lineColor) {
this(source, dest, lineArrow, CONNECT_LINE_TYPE_RECTANGULAR, lineColor);
}
/**
* Constructs a connector with specified arrow, line type and color.
* @param source JComponent
* @param dest JComponent
* @param lineArrow int
* @param lineType int
* @param lineColor Color
*/
public JConnector(JComponent source, JComponent dest, int lineArrow, int lineType, Color lineColor) {
this.source = source;
this.dest = dest;
this.lineArrow = lineArrow;
this.lineType = lineType;
this.lineColor = lineColor;
}
/**
* Overrides parent's paint(). It resets clip to draw connecting line
* between components and set the clip back.
* @param g Graphics
*/
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2d = (Graphics2D) g;
calculateLine();
if (line != null) {
Shape oldClip = g2d.getClip();
g2d.setClip(getLineBounds());
g2d.setColor(lineColor);
line.paint(g2d);
g2d.setClip(oldClip);
}
}
protected void calculateLine() {
Rectangle rSource = source.getBounds();
109
Rectangle rDest = dest.getBounds();
if (rSource.intersects(rDest)) {
line = null;
return;
}
boolean xIntersect = (rSource.x <= rDest.x && rSource.x + rSource.width >= rDest.x)
|| (rDest.x <= rSource.x && rDest.x + rDest.width >= rSource.x);
boolean yIntersect = rSource.y <= rDest.y && rSource.y + rSource.height >= rDest.y
|| (rDest.y <= rSource.y && rDest.y + rDest.height >= rSource.y);
if (xIntersect) {
int y1;
int y2;
int x1 = rSource.x + rSource.width / 2;
int x2 = rDest.x + rDest.width / 2;
if (rSource.y + rSource.height <= rDest.y) {
//source higher
y1 = rSource.y + rSource.height;
y2 = rDest.y;
}
else {
y1 = rSource.y;
y2 = rDest.y + rDest.height;
}
line = new ConnectLine(new Point(x1, y1), new Point(x2, y2), ConnectLine.LINE_TYPE_RECT_VERTICAL,
ConnectLine.LINE_START_VERTICAL, lineArrow);
if (lineType == CONNECT_LINE_TYPE_SIMPLE) {
line.setLineType(ConnectLine.LINE_TYPE_SIMPLE);
}
}
else if (yIntersect) {
int y1 = rSource.y + rSource.height / 2;
;
int y2 = rDest.y + rDest.height / 2;
;
int x1;
int x2;
if (rSource.x + rSource.width <= rDest.x) {
x1 = rSource.x + rSource.width;
x2 = rDest.x;
}
else {
x1 = rSource.x;
x2 = rDest.x + rDest.width;
}
line = new ConnectLine(new Point(x1, y1), new Point(x2, y2), ConnectLine.LINE_TYPE_RECT_HORIZONTAL,
ConnectLine.LINE_START_HORIZONTAL, lineArrow);
if (lineType == CONNECT_LINE_TYPE_SIMPLE) {
line.setLineType(ConnectLine.LINE_TYPE_SIMPLE);
}
}
else {
int y1;
int y2;
int x1;
int x2;
if (rSource.y + rSource.height <= rDest.y) {
//source higher
y1 = rSource.y + rSource.height / 2;
y2 = rDest.y;
if (rSource.x + rSource.width <= rDest.x) {
x1 = rSource.x + rSource.width;
}
else {
x1 = rSource.x;
}
x2 = rDest.x + rDest.width / 2;
}
else {
y1 = rSource.y + rSource.height / 2;
y2 = rDest.y + rDest.height;
if (rSource.x + rSource.width <= rDest.x) {
x1 = rSource.x + rSource.width;
}
else {
x1 = rSource.x;
}
x2 = rDest.x + rDest.width / 2;
}
line = new ConnectLine(new Point(x1, y1), new Point(x2, y2), ConnectLine.LINE_TYPE_RECT_1BREAK,
ConnectLine.LINE_START_HORIZONTAL, lineArrow);
if (lineType == CONNECT_LINE_TYPE_SIMPLE) {
line.setLineType(ConnectLine.LINE_TYPE_SIMPLE);
}
}
}
protected Rectangle getLineBounds() {
int add = 10;
int maxX = Math.max(line.getP1().x, line.getP2().x);
110
int minX = Math.min(line.getP1().x, line.getP2().x);
int maxY = Math.max(line.getP1().y, line.getP2().y);
int minY = Math.min(line.getP1().y, line.getP2().y);
Rectangle res = new Rectangle(minX - add, minY - add, maxX - minX + 2 * add, maxY - minY + 2 * add);
return res;
}
public Color getLineColor() {
return lineColor;
}
public void setLineColor(Color c) {
lineColor = c;
}
public int getLineType() {
return lineType;
}
public void setLineType(int type) {
lineType = type;
}
public int getLineArrow() {
return lineArrow;
}
public void setLineArrow(int arrow) {
lineArrow = arrow;
} }
111
11.1.3 Emulator.java
package xenon;
import
import
import
import
import
import
import
import
import
import
import
import
import
java.awt.Container;
java.awt.EventQueue;
java.awt.event.ActionEvent;
java.awt.event.KeyEvent;
java.awt.event.KeyListener;
java.awt.event.MouseListener;
java.io.BufferedWriter;
java.io.File;
java.io.FileWriter;
java.io.IOException;
java.util.ArrayList;
java.util.Timer;
java.util.TimerTask;
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
javax.swing.AbstractAction;
javax.swing.Action;
javax.swing.GroupLayout;
javax.swing.GroupLayout.Alignment;
javax.swing.filechooser.FileFilter;
javax.swing.ImageIcon;
javax.swing.JButton;
javax.swing.JFileChooser;
javax.swing.JFrame;
javax.swing.JMenu;
javax.swing.JMenuBar;
javax.swing.JMenuItem;
javax.swing.JPanel;
javax.swing.JPopupMenu;
javax.swing.JScrollPane;
javax.swing.JTextPane;
javax.swing.JToolBar;
javax.swing.KeyStroke;
import xenon.DebugViewManager.InputType;
import xenon.Instruction.OperationCode;
/**
* @brief Clase gestora de la vista de emulación.
* @detail Esta clase realiza todas las tareas de la interfaz gráfica de la vista de emulación,
* además de lidiar con la clase VirtualComputer.
*/
public class Emulator extends JFrame implements VirtualComputer.VirtualComputerListener {
private static final long serialVersionUID = 1L;
private JTextPane consoleArea;
//Consola de entrada y salida de datos
//Buffer de entrada. Se van añadiendo datos hasta recibir un enter (en el caso de que el computador esté pidiendo datos)
private String inputBuffer;
//Timer usado para organizar la
ejecución de instrucciones.
private VirtualComputer computer;
//Instancia del computador que se está emulando
private ConsoleKeyListener consolaListener;
//Listener que recoge y trata la entrada proveniente del
teclado
//Si el simulador se está ejecutando en forma standalone, cerrar la ventana cerrará todo
//el programa, en ese caso esta variable valdrá true.
private boolean exitOnClose;
Timer timer;
ExecuteInstructionTask task; //Tarea de ejecución de una instrucción.
private long period;
//Período de reloj de una instrucción del computador en milisegundos = 1000/f
/**
* @brief Tarea que ejecuta una instrucción.
* @detail El timer instructionTimer llamará a la función run() una vez por el período de tiempo fijado.
* Esa función se encarga de ejecutar la siguiente instrucción.
*/
class ExecuteInstructionTask extends TimerTask{
@Override
public void run() {
if(consolaListener.getPidiendoDatos() == InputType.FALSE)
{
actionExecuteNextInstruction();
}
}
public void stop(){
this.cancel();
}
}
/**
*
* @brief Sirve de filtro para mostrar solo los ficheros con la extensión binaria "ece".
*
*/
112
public class BinaryFilter extends FileFilter {
//Aceptar todos los directorios y los ficheros .ece (binarios)
public boolean accept(File f) {
if (f.isDirectory()) {
return true;
}
String arg1 = f.getName().toLowerCase();
if(arg1.lastIndexOf('.')>0)
{
// get last index for '.' char
int lastIndex = arg1.lastIndexOf('.');
// get extension
String extension = arg1.substring(lastIndex);
if (extension != null) {
if (extension.equals(".ece") ) {
return true;
}
}
}
return false;
}
//Descripción de este filtro
public String getDescription() {
return "Binarios";
}
}
/**
* @brief Clase que escucha la entrada del teclado y la representa en la consola.
* @detail Cuando el usuario presione ENTER, los datos se mandarán al computador.
*/
class ConsoleKeyListener implements KeyListener
{
private InputType inputAsked;
/**
* Informa al listener de si el computador está pidiendo datos.
* @param b Define si el computador está pidiendo datos, y de qué tipo
*/
public void setPidiendoDatos(InputType b)
{
inputAsked = b;
if(inputAsked != InputType.FALSE)
{
consoleArea.requestFocus();
if(inputAsked == InputType.CARACTER)
{
consoleArea.setText(consoleArea.getText()
+ "\nIntroduzca un carácter: ");
}
else if(inputAsked == InputType.NUMBER)
{
consoleArea.setText(consoleArea.getText()
+ "\nIntroduzca un número: ");
}
}
}
/**
* @brief Informa de si actualmente el computador está a la espera de datos de entrada.
*/
public InputType getPidiendoDatos()
{
return inputAsked;
}
void displayInfo(KeyEvent e)
{
if(inputAsked != InputType.FALSE)
{
String s = consoleArea.getText();
int id = e.getID();
if (id == KeyEvent.KEY_TYPED) {
s += e.getKeyChar();
}
consoleArea.setText(s);
if(inputBuffer == null)
{
inputBuffer = new String("");
}
if(KeyEvent.VK_ENTER == e.getKeyChar())
{
String in = getConsoleInput();
if(in == null) //Se ha pulsado enter pero no se han introducido datos
{
try{
113
computer.getState().setE(0);
}
catch (Exception x)
{
}
}
else
{
if(inputAsked == InputType.NUMBER) //El dato pedido es un número
{
try{
int inn = Integer.parseInt(in);
try{
computer.getState().setE(inn);
}
catch (Exception xx)
{
//TODO:
}
}
catch (NumberFormatException nfe) {
//TODO:
}
}
else if(inputAsked == InputType.CARACTER) //El dato pedido es un carácter
{
if(in.length() == 1)
{
try{
int inn =
(char)in.charAt(0);//Character.getNumericValue(in.charAt(0));
try{
computer.getState().setE(inn);
}
catch (Exception xx)
{
//TODO:
}
}
catch (NumberFormatException nfe) {
//TODO:
}
}
else
{
//TODO: Error la cadena introducida es demasiado larga
(debería ser 1 solo carácter).
}
}
}
try{
computer.executeNextInstruction();
}
catch(Exception excep)
{
}
setPidiendoDatos(InputType.FALSE);
}
else //Si no se ha pulsado ENTER, añadimos la entrada del teclado al buffer de entrada
{
inputBuffer += e.getKeyChar();
}
}
}
@Override
public void keyPressed(KeyEvent e) {
}
@Override
public void keyReleased(KeyEvent e) {
}
//Esta función es llamada cada vez que se pulsa una tecla mientras la consola esté enfocada.
@Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
displayInfo(e);
}
}
/**
* @detail Devuelve los datos del buffer de entrada del teclado
* @return
*/
114
public String getConsoleInput()
{
String r = null;
if(inputBuffer != null)
{
r = new String(inputBuffer);
}
inputBuffer = null;
return r;
}
/**
* Método main, es el método de entrada del programa, el primero que se ejecuta.
* @param args
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Emulator frame = new Emulator();
frame.pack();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* @brief Método que cambia el título de la ventana del emulador
* @param s
*/
public void setMyTitle(String s)
{
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
exitOnClose = false;
setTitle("Emulador CESIUS - " + s);
}
/**
* @brief Constructor que inicializa la clase
*/
public Emulator(){
super();
setBounds(100, 100, 800, 600);
setTitle("Emulador CESIUS");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
exitOnClose = true;
consoleArea = null;
inputBuffer = "";
computer = new VirtualComputer();
computer.setListener(this);
timer = new Timer("Timer");
task = null;
//Período del reloj de la máquina en milisegundos.
period = 50L;
addComponentToPane(getContentPane());
}
/**
* Añade la cadena text a la consola
* @param text
*/
public void addConsoleOutput(String text)
{
String s = consoleArea.getText();
s += text;
consoleArea.setText(s);
}
/**
* @detail Método que sirve para dar a conocer a la vista de depuración si
* el computador está a la espera de datos.
* @param b
*/
public void setPidiendoDatos(InputType b)
{
consolaListener.setPidiendoDatos(b);
}
/**
* @detail Acción Ejecutar siguiente instrucción. Solo ejecuta una instrucción.
*/
public void actionExecuteNextInstruction()
{
//Check if next instruction needs some kind of input.
OperationCode op = computer.getNextInstruction().getOperationCode();
115
if(op == OperationCode.LCA || op == OperationCode.LCAI )
{
/*
* In that case the instruction will be executed when when we get the input.
*/
setPidiendoDatos(InputType.CARACTER);
}
else if(op == OperationCode.LEE || op == OperationCode.LEEI)
{
/*
* In that case the instruction will be executed when when we get the input.
*/
setPidiendoDatos(InputType.NUMBER);
}
else{
//If it's not needed, execute instruction.
if(op == OperationCode.ALT)
{
actionPause();
}
else
{
try{
computer.executeNextInstruction();
}
catch(Exception e)
{
//TODO: Catch exception
}
}
}
}
/**
* @detail Acción Pausar. Detiene la ejecución de instrucciones.
*/
public void actionPause()
{
if(task != null)
{
task.cancel();
task = null;
}
}
/**
* @brief Inicializa la memoria del computador con cierto código
* @param codeArray Código a ejecutar
*/
public void setRunCode(ArrayList<Instruction> codeArray)
{
actionRestart();
computer.setMemoryMap(codeArray);
actionRun();
}
/**
* @brief Acción Reiniciar. Reinicia el estado del computador.
*/
public void actionRestart()
{
if(task != null)
{
task.cancel();
task = null;
}
consoleArea.setText("");
consolaListener.setPidiendoDatos(InputType.FALSE);
try
{
computer.restart();
actionRun();
}
catch(Exception e)
{
}
}
/**
* @detail Acción "Ejecutar Todo". Ejecuta las instrucciones del ordenador hasta llegar a un ALT,
* con la frecuencia del computador seleccionada.
*/
public void actionRun()
{
if(task == null)
{
consolaListener.setPidiendoDatos(InputType.FALSE);
task = new ExecuteInstructionTask();
116
timer.scheduleAtFixedRate(task, 0, period);
}
}
@Override
public void writeNumberToScreen() {
addConsoleOutput("" + computer.getState().getE());
}
@Override
public void stateChanged() {
}
@Override
public void memoryChanged(Instruction i) {
}
/**
* @brief Añade todos los componentes visuales necesarios al panel.
* @param pane
*/
public void addComponentToPane(Container pane)
{
//A continuación definimos todas las acciones de la vista de emulación
java.net.URL imageURL = Interface.class.getResource("images/gtk-quit.png");
ImageIcon icon = new ImageIcon(imageURL);
Action actionSalir = new AbstractAction("Salir", icon) {
/**
*
*/
private static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent e) {
if(exitOnClose)
{
//Cerrar todo
System.exit(0);
}
else
{
//No cierra toda la aplicación, solo esta ventana.
dispose();
}
}
};
imageURL = Interface.class.getResource("images/gnome-fs-directory.png");
icon = new ImageIcon(imageURL);
Action actionAbrirEjecutable = new AbstractAction("Abrir Ejecutable", icon) {
/**
*
*/
private static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent e) {
JFileChooser SaveAs = new JFileChooser();
ProjectFile.FileType.BINARY)
SaveAs.setFileFilter(new BinaryFilter());
SaveAs.setAcceptAllFileFilterUsed(false);
int actionDialog = SaveAs.showDialog(null, "Abrir");
if(actionDialog == JFileChooser.APPROVE_OPTION)
{
String path = SaveAs.getSelectedFile().getPath();
File fileName = new File(path);
if (fileName != null)
{
ProjectFile codeToExecute = new ProjectFile(fileName,null);
if(codeToExecute != null && codeToExecute.type ==
{
try {
//CesiusHelper core = new CesiusHelper();
ArrayList<Instruction> in =
XenonHelper.openBinaryFile(codeToExecute.file);
setRunCode(in);
System.out.println("Ejecutando binario: " +
codeToExecute.file.getName());
setTitle("Emulador CESIUS - " +
codeToExecute.file.getPath());
}
catch(Exception x){
System.out.println(x.getMessage());
}
}
}
}
117
}
};
imageURL = Interface.class.getResource("images/document-save.png");
icon = new ImageIcon(imageURL);
Action actionGuardar = new AbstractAction("Guardar Texto de Consola", icon) {
/**
*
*/
private static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent e) {
JFileChooser SaveAs = new JFileChooser();
int actionDialog = SaveAs.showDialog(null, "Guardar Como...");
if(actionDialog == JFileChooser.APPROVE_OPTION)
{
String path = SaveAs.getSelectedFile().getPath();
File fileName = new File(path);
if (fileName != null)
{
System.out.println("Guardando " + path + " ...");
try {
BufferedWriter outFile = new BufferedWriter(new
FileWriter(fileName));
outFile.write(consoleArea.getText()); //put in textfile
outFile.close();
}
catch (IOException ex) {
}
}
}
}
};
Action actionLimpiarProblemas = new AbstractAction("Limpiar", null) {
/**
*
*/
private static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent e) {
consoleArea.setText("");
}
};
imageURL = Interface.class.getResource("images/reload.png");
icon = new ImageIcon(imageURL);
Action actionReiniciar = new AbstractAction("Reiniciar máquina", icon) {
/**
*
*/
private static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent e) {
actionRestart();
actionRun();
}
};
//A continuación definimos la barra de menús
JMenuBar menuBar = new JMenuBar();
JMenu menu;
JMenuItem menuItem;
menu = new JMenu("Archivo");
menuBar.add(menu);
menuItem = menu.add(actionAbrirEjecutable);
menu.add(menuItem);
menuItem = menu.add(actionGuardar);
menu.add(menuItem);
menu = new JMenu("Emulador");
menuBar.add(menu);
menuItem = menu.add(actionReiniciar);
menu.add(menuItem);
menuItem = menu.add(actionSalir);
menuItem.setAccelerator(KeyStroke.getKeyStroke(
KeyEvent.VK_ESCAPE, ActionEvent.CTRL_MASK));
menu.add(menuItem);
//A continuación, la barra de herramientas
JToolBar toolBar;
toolBar = new JToolBar();
toolBar.setFloatable(false);
118
JButton button = toolBar.add(actionAbrirEjecutable);
button.setToolTipText("Abrir Ejecutable");
button = toolBar.add(actionGuardar);
button.setToolTipText("Guardar texto de la consola");
button = toolBar.add(actionReiniciar);
button.setToolTipText("Reiniciar máquina");
//Iniciamos la consola
consoleArea = new JTextPane();
consoleArea.setEditable(false);
//Con esto, el enter será sólo un carácter raro sin efecto
consoleArea.setFocusTraversalKeysEnabled(false);
consolaListener = new ConsoleKeyListener();
consoleArea.addKeyListener(consolaListener);
consolaListener.setPidiendoDatos(InputType.FALSE);
JScrollPane scrollPane = new JScrollPane(consoleArea);
JPanel codeJPanel = new JPanel();
//Añadimos el popup de limpiar consola
JPopupMenu popup = new JPopupMenu();
popup.add(actionLimpiarProblemas);
MouseListener popupListener = new PopupListener(popup);
consoleArea.addMouseListener(popupListener);
//Aquí definimos la disposición gráfica de los componentes en la vista de emulación.
GroupLayout gl_menu1 = new GroupLayout(codeJPanel);
gl_menu1.setHorizontalGroup(
gl_menu1.createParallelGroup(Alignment.LEADING)
.addComponent(menuBar, 0, 800, Short.MAX_VALUE)
.addComponent(toolBar, 0, 800, Short.MAX_VALUE)
.addComponent(scrollPane, 0, 800, Short.MAX_VALUE)
);
gl_menu1.setVerticalGroup(
gl_menu1.createParallelGroup(Alignment.LEADING)
.addGroup(gl_menu1.createSequentialGroup()
.addComponent(menuBar, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE,
GroupLayout.PREFERRED_SIZE)
.addComponent(toolBar, GroupLayout.PREFERRED_SIZE, 24, GroupLayout.PREFERRED_SIZE)
.addComponent(scrollPane, 0, 560, Short.MAX_VALUE)
)
);
codeJPanel.setLayout(gl_menu1);
pane.add(codeJPanel);
}
@Override
public void writeCharacterToScreen() {
// TODO Auto-generated method stub
char c = (char)computer.getState().getE();
addConsoleOutput(Character.toString(c));
}
}
119
11.1.4 ConnectLine.java
package xenon;
import java.awt.*;
import java.awt.geom.Point2D;
/**
* The class represents base line model and rendering according to multiple params.
*
* <p>Copyright: Copyright (c) 2007</p>
*
* @author Stanislav Lapitsky
* @version 1.0
*/
/**
* @brief Una de las clases usada para pintar flechitas de un lado a otro
* @detail Librería modificada por Félix Robles, código original de Stanislav Lapitsky.
*/
public class ConnectLine {
public static final int LINE_TYPE_SIMPLE = 0;
public static final int LINE_TYPE_RECT_1BREAK = 1;
public static final int LINE_TYPE_RECT_2BREAK = 2;
public static final int LINE_TYPE_RECT_HORIZONTAL = 3;
public static final int LINE_TYPE_RECT_VERTICAL = 4;
public static final int LINE_START_HORIZONTAL = 0;
public static final int LINE_START_VERTICAL = 1;
public
public
public
public
static
static
static
static
final
final
final
final
int
int
int
int
LINE_ARROW_NONE =
LINE_ARROW_SOURCE
LINE_ARROW_DEST =
LINE_ARROW_BOTH =
0;
= 1;
2;
3;
public static int LINE_ARROW_WIDTH = 5;
/**
* Source line point
*/
Point p1;
/**
* Destination line point
*/
Point p2;
/**
* Line type can be one of LINE_TYPE_SIMPLE, LINE_TYPE_RECT_1BREAK, LINE_TYPE_RECT_2BREAK
*/
int lineType = LINE_TYPE_SIMPLE;
/**
* for the LINE_TYPE_RECT_2BREAK type the param defines how line should be rendered
*/
int lineStart = LINE_START_HORIZONTAL;
/**
* arrow can be one of following
* LINE_ARROW_NONE - no arrow
* LINE_ARROW_SOURCE - arrow beside source point
* LINE_ARROW_DEST - arrow beside dest point
* LINE_ARROW_BOTH - both source and dest has arrows
*/
int lineArrow = LINE_ARROW_NONE;
/**
* Constructs default line
* @param p1 Point start
* @param p2 Point end
*/
public ConnectLine(Point p1, Point p2) {
this(p1, p2, LINE_TYPE_SIMPLE, LINE_START_HORIZONTAL, LINE_ARROW_NONE);
}
/**
* Constructs line with specified params
* @param p1 Point start
* @param p2 Point end
* @param lineType int type of line (LINE_TYPE_SIMPLE, LINE_TYPE_RECT_1BREAK, LINE_TYPE_RECT_2BREAK)
* @param lineStart int for the LINE_TYPE_RECT_2BREAK type the param defines how line should be rendered
* @param lineArrow int defines line arrow type
*/
public ConnectLine(Point p1, Point p2, int lineType, int lineStart, int lineArrow) {
this.p1 = p1;
this.p2 = p2;
this.lineType = lineType;
this.lineStart = lineStart;
this.lineArrow = lineArrow;
}
/**
* Paints the line with specified params
* @param g2d Graphics2D
*/
public void paint(Graphics2D g2d) {
120
switch (lineType) {
case LINE_TYPE_SIMPLE:
paintSimple(g2d);
break;
case LINE_TYPE_RECT_1BREAK:
paint1Break(g2d);
break;
case LINE_TYPE_RECT_2BREAK:
paint2Breaks(g2d);
break;
case LINE_TYPE_RECT_HORIZONTAL:
paintHorizontal(g2d);
break;
case LINE_TYPE_RECT_VERTICAL:
paintVertical(g2d);
break;
}
}
protected void paintVertical(Graphics2D g2d) {
Point pp1 = new Point(p1.x, p1.y);
Point pp2 = new Point(p1.x, p2.y);
g2d.drawLine(p1.x, p1.y, p1.x, p2.y);
switch (lineArrow) {
case LINE_ARROW_DEST:
paintArrow(g2d, pp1, pp2);
break;
case LINE_ARROW_SOURCE:
paintArrow(g2d, pp2, pp1);
break;
case LINE_ARROW_BOTH:
paintArrow(g2d, pp1, pp2);
paintArrow(g2d, pp2, pp1);
break;
}
}
protected void paintHorizontal(Graphics2D g2d) {
Point pp1 = new Point(p1.x, p1.y);
Point pp2 = new Point(p2.x, p1.y);
g2d.drawLine(p1.x, p1.y, p2.x, p1.y);
switch (lineArrow) {
case LINE_ARROW_DEST:
paintArrow(g2d, pp1, pp2);
break;
case LINE_ARROW_SOURCE:
paintArrow(g2d, pp2, pp1);
break;
case LINE_ARROW_BOTH:
paintArrow(g2d, pp1, pp2);
paintArrow(g2d, pp2, pp1);
break;
}
}
protected void paintSimple(Graphics2D g2d) {
g2d.drawLine(p1.x, p1.y, p2.x, p2.y);
switch (lineArrow) {
case LINE_ARROW_DEST:
paintArrow(g2d, p1, p2);
break;
case LINE_ARROW_SOURCE:
paintArrow(g2d, p2, p1);
break;
case LINE_ARROW_BOTH:
paintArrow(g2d, p1, p2);
paintArrow(g2d, p2, p1);
break;
}
}
protected void paintArrow(Graphics2D g2d, Point p1, Point p2) {
paintArrow(g2d, p1, p2, getRestrictedArrowWidth(p1, p2));
}
protected void paintArrow(Graphics2D g2d, Point p1, Point p2, int width) {
Point2D.Float pp1 = new Point2D.Float(p1.x, p1.y);
Point2D.Float pp2 = new Point2D.Float(p2.x, p2.y);
Point2D.Float left = getLeftArrowPoint(pp1, pp2, width);
Point2D.Float right = getRightArrowPoint(pp1, pp2, width);
Polygon arrowHead =
arrowHead.addPoint(
arrowHead.addPoint(
arrowHead.addPoint(
new Polygon();
p2.x, p2.y);
Math.round(left.x), Math.round(left.y));
Math.round(right.x), Math.round(right.y));
Graphics2D g = (Graphics2D) g2d.create();
g.fill(arrowHead);
g.dispose();
/*
g2d.drawLine(p2.x, p2.y, Math.round(left.x), Math.round(left.y));
g2d.drawLine(p2.x, p2.y, Math.round(right.x), Math.round(right.y));
*/
}
121
protected void paint1Break(Graphics2D g2d) {
if (lineStart == LINE_START_HORIZONTAL) {
g2d.drawLine(p1.x, p1.y, p2.x, p1.y);
g2d.drawLine(p2.x, p1.y, p2.x, p2.y);
switch (lineArrow) {
case LINE_ARROW_DEST:
paintArrow(g2d, new Point(p2.x, p1.y),
break;
case LINE_ARROW_SOURCE:
paintArrow(g2d, new Point(p2.x, p1.y),
break;
case LINE_ARROW_BOTH:
paintArrow(g2d, new Point(p2.x, p1.y),
paintArrow(g2d, new Point(p2.x, p1.y),
break;
}
}
else if (lineStart == LINE_START_VERTICAL) {
g2d.drawLine(p1.x, p1.y, p1.x, p2.y);
g2d.drawLine(p1.x, p2.y, p2.x, p2.y);
switch (lineArrow) {
case LINE_ARROW_DEST:
paintArrow(g2d, new Point(p1.x, p2.y),
break;
case LINE_ARROW_SOURCE:
paintArrow(g2d, new Point(p1.x, p2.y),
break;
case LINE_ARROW_BOTH:
paintArrow(g2d, new Point(p1.x, p2.y),
paintArrow(g2d, new Point(p1.x, p2.y),
break;
}
}
}
p2);
p1);
p2);
p1);
p2);
p1);
p2);
p1);
protected void paint2Breaks(Graphics2D g2d) {
if (lineStart == LINE_START_HORIZONTAL) {
g2d.drawLine(p1.x, p1.y, p1.x + (p2.x - p1.x) / 2, p1.y);
g2d.drawLine(p1.x + (p2.x - p1.x) / 2, p1.y, p1.x + (p2.x - p1.x) / 2, p2.y);
g2d.drawLine(p1.x + (p2.x - p1.x) / 2, p2.y, p2.x, p2.y);
switch (lineArrow) {
case LINE_ARROW_DEST:
paintArrow(g2d, new Point(p1.x + (p2.x - p1.x) / 2, p2.y), p2);
break;
case LINE_ARROW_SOURCE:
paintArrow(g2d, new Point(p1.x + (p2.x - p1.x) / 2, p1.y), p1);
break;
case LINE_ARROW_BOTH:
paintArrow(g2d, new Point(p1.x + (p2.x - p1.x) / 2, p2.y), p2);
paintArrow(g2d, new Point(p1.x + (p2.x - p1.x) / 2, p1.y), p1);
break;
}
}
else if (lineStart == LINE_START_VERTICAL) {
g2d.drawLine(p1.x, p1.y, p1.x, p1.y + (p2.y - p1.y) / 2);
g2d.drawLine(p1.x, p1.y + (p2.y - p1.y) / 2, p2.x, p1.y + (p2.y - p1.y) / 2);
g2d.drawLine(p2.x, p1.y + (p2.y - p1.y) / 2, p2.x, p2.y);
switch (lineArrow) {
case LINE_ARROW_DEST:
paintArrow(g2d, new
break;
case LINE_ARROW_SOURCE:
paintArrow(g2d, new
break;
case LINE_ARROW_BOTH:
paintArrow(g2d, new
paintArrow(g2d, new
break;
}
Point(p2.x, p1.y + (p2.y - p1.y) / 2), p2);
Point(p1.x, p1.y + (p2.y - p1.y) / 2), p1);
Point(p2.x, p1.y + (p2.y - p1.y) / 2), p2);
Point(p1.x, p1.y + (p2.y - p1.y) / 2), p1);
}
}
public int getLineType() {
return lineType;
}
public void setLineType(int type) {
lineType = type;
}
public int getLineStart() {
return lineStart;
}
public void setLineStart(int start) {
lineStart = start;
}
public int getLineArrow() {
return lineArrow;
122
}
public void setLineArrow(int arrow) {
lineType = lineArrow;
}
public Point getP1() {
return p1;
}
public void setP1(Point p) {
p1 = p;
}
public Point getP2() {
return p2;
}
public void setP2(Point p) {
p2 = p;
}
protected static Point2D.Float getMidArrowPoint(Point2D.Float p1, Point2D.Float p2, float w) {
Point2D.Float res = new Point2D.Float();
float d = Math.round(Math.sqrt( (p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y)));
if (p1.x < p2.x) {
res.x = p2.x - w * Math.abs(p1.x - p2.x) / d;
}
else {
res.x = p2.x + w * Math.abs(p1.x - p2.x) / d;
}
if (p1.y < p2.y) {
res.y = p2.y - w * Math.abs(p1.y - p2.y) / d;
}
else {
res.y = p2.y + w * Math.abs(p1.y - p2.y) / d;
}
return res;
}
protected static Point2D.Float getLeftArrowPoint(Point2D.Float p1, Point2D.Float p2) {
return getLeftArrowPoint(p1, p2, LINE_ARROW_WIDTH);
}
protected static Point2D.Float getLeftArrowPoint(Point2D.Float p1, Point2D.Float p2, float w) {
Point2D.Float res = new Point2D.Float();
double alpha = Math.PI / 2;
if (p2.x != p1.x) {
alpha = Math.atan( (p2.y - p1.y) / (p2.x - p1.x));
}
alpha += Math.PI / 5;
float xShift = Math.abs(Math.round(Math.cos(alpha) * w));
float yShift = Math.abs(Math.round(Math.sin(alpha) * w));
if (p1.x <= p2.x) {
res.x = p2.x - xShift;
}
else {
res.x = p2.x + xShift;
}
if (p1.y < p2.y) {
res.y = p2.y - yShift;
}
else {
res.y = p2.y + yShift;
}
return res;
}
protected static Point2D.Float getRightArrowPoint(Point2D.Float p1, Point2D.Float p2) {
return getRightArrowPoint(p1, p2, LINE_ARROW_WIDTH);
}
protected static Point2D.Float getRightArrowPoint(Point2D.Float p1, Point2D.Float p2, float w) {
Point2D.Float res = new Point2D.Float();
double alpha = Math.PI / 2;
if (p2.x != p1.x) {
alpha = Math.atan( (p2.y - p1.y) / (p2.x - p1.x));
}
alpha -= Math.PI / 5;
float xShift = Math.abs(Math.round(Math.cos(alpha) * w));
float yShift = Math.abs(Math.round(Math.sin(alpha) * w));
if (p1.x < p2.x) {
res.x = p2.x - xShift;
}
else {
res.x = p2.x + xShift;
}
if (p1.y <= p2.y) {
res.y = p2.y - yShift;
123
}
else {
res.y = p2.y + yShift;
}
return res;
}
protected int getRestrictedArrowWidth(Point p1, Point p2) {
return Math.min(LINE_ARROW_WIDTH, (int) Math.sqrt( (p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y)));
}
}
124
11.1.5 LineCode.java
package xenon;
import xenon.XenonHelper.PseudoInstruction;
/**
* @brief Contiene la información de una línea de texto del código ensamblador.
* Es una clase intermediaria usada en la compilación del código ensamblador.
*/
public class LineCode{
public Instruction instruction;
public String label;
public int address; //Posición de memoria donde se encuentra esta instrucción, no confundir con
LineCode.instruction.getMemoryAddress.
public String addressLabel; // Necesario en un paso intermedio. Hay que traducirlo y meterlo en
LineCode.instruction.setMemoryAddress.
public int lineNumber;
public PseudoInstruction pseudoInstruction;
LineCode()
{
instruction = new Instruction();
label = null;
address = -1;
addressLabel = null;
pseudoInstruction = null;
lineNumber = -1;
}
public String toString()
{
String s = new String();
return s;
}
public int check()
{
int r = 0;
if(lineNumber < 0)
{
r = -1;
}
else if(address < 0 || address > Instruction.Memory_Address_Limit)
{
System.out.println("Error: address " + address + " out of bounds");
r = -2;
}
else if(pseudoInstruction == null)
{
if(instruction == null)
{
r = -3;
}
else if( instruction.isInstruction() )
{
//Es una instrucción
}
else if( !instruction.isInstruction() )
{
//Es simplemente datos
}
}
else if(pseudoInstruction != null)
{
switch(pseudoInstruction)
{
case ORG:
case FIN:
case ESP:
case CTE:
//Todo OK
break;
//No deberíamos haber guardado esta pseudo instrucción!!
r = -4;
break;
int d = 0;
try {
instruction.setInstructionSigned(d);
}
catch(Exception e)
{
}
break;
break;
}
}
return r;
} };
125
11.1.6 Sobre.java
package xenon;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import
import
import
import
import
javax.swing.JButton;
javax.swing.JDialog;
javax.swing.JLabel;
javax.swing.UIManager;
javax.swing.GroupLayout;
/**
* @brief Esta clase implementa una ventana popup que muestra información sobre el autor
* del proyecto, así como del profesor tutor del mismo.
*
*/
public class Sobre extends JDialog
implements ActionListener{
/**
*
*/
private static final long serialVersionUID = 1L;
/**
* Lanzar ventana/aplicación
*/
public static void main(String[] args) {
try {
Sobre dialog = new Sobre(0,0);
dialog.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
public void actionPerformed(ActionEvent e) {
//No cierra toda la aplicación, solo esta ventana.
dispose();
}
/**
* Crear diálogo.
*/
public Sobre(int xoffset, int yoffset) {
setBounds(285+xoffset, 220+yoffset, 360, 245);
setTitle("Sobre este programa");
setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
JLabel infoIcon = new JLabel( UIManager.getIcon("OptionPane.informationIcon"));
JLabel info1 = new JLabel("
CESIUS IDE v0.3");
JLabel info2 = new JLabel("© Copyright 2013");
JLabel info3 = new JLabel("Proyecto Fin de Carrera");
JLabel info4 = new JLabel("E.T.S.I. Universidad de Sevilla");
JLabel info5 = new JLabel("Autor: Félix Robles Elvira,");
JLabel info6 = new JLabel("e-mail: [email protected]");
JLabel info7 = new JLabel("Tutor: José Ángel Acosta Rodríguez,");
JLabel info8 = new JLabel("e-mail: [email protected]");
JLabel info9 = new JLabel("Licencia GPLv3.0");
JButton okButton = new JButton("OK");
okButton.addActionListener(this);
GroupLayout groupLayout = new GroupLayout(getContentPane());
groupLayout.setHorizontalGroup(
groupLayout.createSequentialGroup()
.addGap(30)
.addComponent(infoIcon)
.addGroup(groupLayout.createParallelGroup(GroupLayout.Alignment.CENTER)
.addComponent(info1)
.addComponent(info2)
.addComponent(info3)
.addComponent(info4)
.addComponent(info5)
.addComponent(info6)
.addComponent(info7)
.addComponent(info8)
.addComponent(info9)
.addComponent(okButton)
)
);
groupLayout.setVerticalGroup(groupLayout.createSequentialGroup()
.addGap(10)
.addGroup(groupLayout.createParallelGroup(GroupLayout.Alignment.BASELINE)
.addComponent(infoIcon)
.addComponent(info1)
)
.addComponent(info2)
.addComponent(info3)
126
.addComponent(info4)
.addComponent(info5)
.addComponent(info6)
.addComponent(info7)
.addComponent(info8)
.addComponent(info9)
.addGap(20)
.addComponent(okButton)
);
getContentPane().setLayout(groupLayout);
}
}
127
11.1.7 ConnectorContainer.java
package xenon;
import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
/**
* The collateral class contains array of connectors and renders them.
* The rendering can be called in a different way. E.g. JConnectors can be just
* added as usual component. In this case programmer must care about their size,
* and layout.
*
* <p>Copyright: Copyright (c) 2007</p>
*
* @author Stanislav Lapitsky
* @version 1.0
*/
/**
* @brief Una de las clases usada para pintar flechitas de un lado a otro
* @detail Librería modificada por Félix Robles, código original de Stanislav Lapitsky.
*/
public class ConnectorContainer extends JPanel {
/**
*
*/
private static final long serialVersionUID = 1L;
ArrayList<JConnector> connectors;
/**
* @brief Constructor de la clase, inicializa el atributo connectors.
*/
public ConnectorContainer() {
connectors = new ArrayList<JConnector> ();
}
/**
* @brief Añade un conector al panel.
*/
public void addConnector(JConnector c)
{
connectors.add(c);
}
/**
* @brief Añade una lista de conectores al panel.
*/
public void addConnectors(ArrayList<JConnector> c)
{
for(JConnector i: c)
{
connectors.add(i);
}
}
/**
* @brief Devuelve los conectores del panel.
*/
public ArrayList<JConnector> getConnectors() {
return connectors;
}
/**
* @brief Pinta los conectores del panel.
*/
public void paint(Graphics g) {
super.paint(g);
for(JConnector c: connectors)
{
c.paint(g);
}
}
}
128
11.1.8 PopupListener.java
package xenon;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JPopupMenu;
/**
*
* @brief Esta clase hace de listener de forma que muestra un popup cuando lo activa el ratón.
*
*/
class PopupListener extends MouseAdapter {
private JPopupMenu popup;
PopupListener(JPopupMenu p)
{
popup = p;
}
public void mousePressed(MouseEvent e) {
showPopup(e);
}
public void mouseReleased(MouseEvent e) {
showPopup(e);
}
private void showPopup(MouseEvent e) {
if (e.isPopupTrigger()) {
popup.show(e.getComponent(),
e.getX(), e.getY());
}
}
}
129
11.1.9 Tab.java
package xenon;
import
import
import
import
java.awt.event.KeyEvent;
java.awt.event.KeyListener;
java.io.BufferedReader;
java.io.FileReader;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import xenon.ProjectFile.FileType;
/**
*
* @brief Esta clase define una pestaña.
*
*/
public class Tab extends JScrollPane implements KeyListener{
/**
*
*/
public static final long serialVersionUID = -8100218024452896927L;
public ProjectFile pFile;
//Fichero que contiene la pestaña
public JTextArea textArea; //Área de texto de la pestaña
private JLabel label;
//Etiqueta de la pestaña
private boolean isModified; //Indica si el texto ha sido modificado y todavía no se ha guardado
/**
* @brief Modifica la etiqueta de la pestaña.
* @param l
*/
public void setLabel(JLabel l)
{
label = l;
}
/**
* @brief Indica si hay cambios no guardados del fichero.
* @return
*/
public boolean isModified()
{
return isModified;
}
/**
* @brief Marca el fichero como modificado/no modificado.
* @param b
*/
public void setModified(boolean b)
{
if(isModified == false && b == true)
{
label.setText("*" + label.getText());
}
else if (isModified == true && b == false)
{
label.setText(label.getText().substring(1));
}
isModified = b;
}
/**
* Constructor
* @param ta JTextArea de la pestaña
* @param pf Fichero que contiene la pestaña
*/
Tab(JTextArea ta, ProjectFile pf)
{
super(ta);
textArea = ta;
pFile = pf;
isModified = false;
label = null;
if(pFile.type == ProjectFile.FileType.TEXT || pFile.type == ProjectFile.FileType.CODE)
{
try {
String strLine;
BufferedReader br = new BufferedReader(new FileReader(pFile.file));
while((strLine = br.readLine()) != null)
{
textArea.append(strLine + "\n");
}
}
catch(Exception e)
{
130
}
System.err.println("Error: " + e.getMessage());
}
else if(pFile.type == ProjectFile.FileType.BINARY)
{
textArea.setEditable(false);
}
textArea.addKeyListener(this);
}
/**
* Al escribir en una pestaña, indicamos que el archivo de texto está siendo modificado.
*/
@Override
public void keyPressed(KeyEvent arg0) {
if(pFile.type != FileType.BINARY)
{
setModified(true);
}
}
@Override
public void keyReleased(KeyEvent arg0) {
}
@Override
public void keyTyped(KeyEvent arg0) {
}
}
131
11.1.10 DebugViewManager.java
package xenon;
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
java.awt.Color;
java.awt.Component;
java.awt.Dimension;
java.awt.event.ActionEvent;
java.awt.event.ItemEvent;
java.awt.event.ItemListener;
java.awt.event.KeyEvent;
java.awt.event.KeyListener;
java.awt.event.MouseListener;
java.beans.PropertyChangeEvent;
java.beans.PropertyChangeListener;
java.io.BufferedWriter;
java.io.File;
java.io.FileWriter;
java.io.IOException;
java.util.ArrayList;
java.util.Timer;
java.util.TimerTask;
java.util.Vector;
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
javax.swing.AbstractAction;
javax.swing.Action;
javax.swing.BorderFactory;
javax.swing.GroupLayout;
javax.swing.GroupLayout.Alignment;
javax.swing.ImageIcon;
javax.swing.JLabel;
javax.swing.JPopupMenu;
javax.swing.JScrollPane;
javax.swing.JSplitPane;
javax.swing.JTabbedPane;
javax.swing.JTable;
javax.swing.JTextField;
javax.swing.JTextPane;
javax.swing.ListSelectionModel;
javax.swing.event.ListSelectionEvent;
javax.swing.event.ListSelectionListener;
javax.swing.table.DefaultTableCellRenderer;
javax.swing.table.DefaultTableModel;
import xenon.VirtualComputer.ComputerRegister;
import xenon.VirtualComputer.ComputerSignal;
import xenon.VirtualComputer.ComputerState;
/**
* @brief Clase gestora de la vista de depuración.
* @detail Esta clase realiza todas las tareas de la interfaz gráfica de la vista de depuración,
* además de lidiar con la clase VirtualComputer.
*/
public class DebugViewManager extends JSplitPane implements VirtualComputer.VirtualComputerListener, ItemListener{
/**
*
* @brief Base usada para representar los registros y el contenido de la memoria.
*
*/
public enum Base { BINARY, DECIMAL, HEXADECIMAL };
/**
*
* @brief FALSE: Actualmente no se está pidiendo ningún dato de entrada.
*
CARACTER: El computador necesita un carácter como dato de entrada.
*
NUMBER: El computador necesita un número como dato de entrada.
*
*/
public enum InputType {
FALSE,CARACTER, NUMBER
};
private boolean isCheckBoxSelected, executeSemisteps;
private JTextPane consolaPane;
//Consola
private ConsoleKeyListener consolaListener;
//Listener que recoge y trata
//Buffer de entrada. Se van añadiendo datos hasta recibir un enter (en el caso de que el
private String inputBuffer;
private long period;
del computador en milisegundos = 1000/f
private int runTo;
dirección de memoria en la que parar la ejecución
private ColorCellRenderer pTableRenderer;
//Renderer de la tabla pTable
private ColorCellRenderer memoriaTableRenderer;//Renderer de la tabla memoriaTable
private File debugFile;
private Trace execTrace;
//Variables que sirven para mantener la cuenta del reloj del computador
public long startTime;
132
de entrada y salida de datos
la entrada proveniente del teclado
computador esté pidiendo datos)
//Período de reloj de una instrucción
//En el caso de "Ejecutar Hasta",
public long nextTime, nextTime2;
//Timer usado para organizar la ejecución de instrucciones en modo runMode
Timer instructionTimer;
//Timer usado para los cambios de registro
Timer changesTimer;
//Tarea de ejecución de una instrucción
ExecuteInstructionTask instructionTask;
//Etiqueta del reloj del computador
JLabel timeLabel;
//Tablas de memoria. pTable muestra la memoria entorno a P.
private JTable pTable, memoriaTable;
//Etiquetas que muestran el contenido de los registros del computador
private FlashyTextField textFieldA, textFieldP, textFieldS, textFieldI, textFieldT, textFieldE, textFieldCO, textFieldMD;
//Etiquetas que muestran las señales del computador
private FlashySignal etLabel, stLabel, eeLabel, seLabel, escpLabel, leetLabel, eaLabel, saLabel, eoLabel,
sumaLabel, resaLabel, multaLabel, incpLabel, epLabel, spLabel, esLabel, sdLabel, eiLabel, lecmLabel, escmLabel, divaLabel,
modaLabel;
//Etiquetas CO/MD/D que han de ser no visibles cuando no estamos en modo binario
JLabel coLabel, mdLabel, dLabel;
//Variable que contiene la base que actualmente se usa para representar datos
private Base base;
//Instancia del computador que se está emulando
private VirtualComputer computer;
/**
*
*/
private static final long serialVersionUID = 1L;
/**
* @brief Esta clase sirve para crear una traza de la ejecución del programa.
*/
class Trace{
File f;
Trace(File file)
{
String dir = file.getParent();
f = new File(dir + "/traza.txt");
System.out.println(f.getAbsolutePath());
restart();
}
public void restart(){
try {
BufferedWriter outFile = new BufferedWriter(new FileWriter(f, false));
outFile.write("Address\t\tP\t\tI\t\tA\t\tT\t\tS\t\tS");
outFile.newLine();
outFile.close();
}
catch (IOException ex) {
}
}
public void registerStep(Instruction i, VirtualComputer.ComputerState s){
try {
BufferedWriter outFile = new BufferedWriter(new FileWriter(f, true));
outFile.write(i.getAddressLocation() + "\t\t" + s.getP() + "\t\t" + i.getOperationCode().name() + " " +
i.getInstructionOperator()
+ "\t\t" + s.getA() + "\t\t" + s.getT() + "\t\t" + s.getS() + "\t\t" + s.getE()); //put in textfile
outFile.newLine();
outFile.close();
}
catch (IOException ex) {
}
}
}
/**
* @brief Tarea que ejecuta una instrucción.
* @detail El timer instructionTimer llamará a la función run() una vez por el período de tiempo fijado.
* Esa función se encarga de ejecutar la siguiente instrucción.
*/
class ExecuteInstructionTask extends TimerTask{
@Override
public void run() {
//Hemos llegado a la instrucción en la que queríamos parar
if(runTo != -1 && computer.getState().getP() == runTo)
{
actionPause();
}
//Si el computador no está pidiendo datos de entrada, ejecutamos la siguiente instrucción
else if(consolaListener.getPidiendoDatos() == InputType.FALSE)
{
executeNextInstruction();
if(startTime > 0)
{
//Actualizamos el tiempo de ejecución después de ejecutar cada instrucción
timeLabel.setText(addZeros((System.currentTimeMillis()-startTime)+"", 6) + " ms");
133
}
}
}
public void stop(){
this.cancel();
}
}
/**
* @brief Clase que escucha cuándo se selecciona una nueva posición de memoria.
* @detail Cuando el usuario seleccione una posición de memoria en la tabla, el registro P cambiará su valor.
*/
class TableListener implements ListSelectionListener
{
@Override
public void valueChanged(ListSelectionEvent arg0) {
try{
if(computer.getState().getP() != pTable.getSelectedRow())
{
consolaListener.setPidiendoDatos(InputType.FALSE);
computer.getState().setP(pTable.getSelectedRow());
computer.getState().setRegisterChanged(ComputerRegister.P, true);
computer.getState().sendSignals();
}
}
catch(Exception e)
{
}
}
}
/**
* @brief Clase que escucha la entrada del teclado y la representa en la consola.
* @detail Cuando el usuario presione ENTER, los datos se mandarán al computador.
*/
class ConsoleKeyListener implements KeyListener
{
private InputType inputAsked;
/**
* Informa al listener de si el computador está pidiendo datos.
* @param b Define si el computador está pidiendo datos, y de qué tipo
*/
public void setPidiendoDatos(InputType b)
{
inputAsked = b;
if(inputAsked != InputType.FALSE)
{
consolaPane.requestFocus();
if(inputAsked == InputType.CARACTER)
{
consolaPane.setText(consolaPane.getText()
+ "\nIntroduzca un carácter: ");
}
else if(inputAsked == InputType.NUMBER)
{
consolaPane.setText(consolaPane.getText()
+ "\nIntroduzca un número: ");
}
}
}
/**
* @brief Informa de si actualmente el computador está a la espera de datos de entrada.
*/
public InputType getPidiendoDatos()
{
return inputAsked;
}
void displayInfo(KeyEvent e)
{
if(e.getModifiers() == 0 &&inputAsked != InputType.FALSE)
{
String s = consolaPane.getText();
int id = e.getID();
if (id == KeyEvent.KEY_TYPED) {
s += e.getKeyChar();
}
consolaPane.setText(s);
if(inputBuffer == null)
134
{
inputBuffer = new String("");
}
//Cuando se pulsa Enter, se envían los datos al computador
if(KeyEvent.VK_ENTER == e.getKeyChar())
{
String in = getConsoleInput();
Instruction.OperationCode op = computer.getNextInstruction().getOperationCode();
Instruction nextIns = new Instruction();
try{
nextIns.setInstructionSigned(computer.getNextInstruction().getDataSigned());
nextIns.setAddressLocation(computer.getNextInstruction().getAddressLocation());
} catch (Exception ee)
{
}
if(in == null)
{
//Se ha pulsado enter pero no se han introducido datos
try{
computer.getState().setE(0);
computer.getState().setRegisterChanged(ComputerRegister.E, true);
computer.getState().sendSignals();
}
catch (Exception x)
{
}
}
else
{
if(inputAsked == InputType.NUMBER)
{
//El dato pedido es un número
try{
int inn = Integer.parseInt(in);
try{
computer.getState().setE(inn);
computer.getState().setRegisterChanged(ComputerRegister.E, true);
computer.getState().sendSignals();
}
catch (Exception xx)
{
//TODO:
}
}
catch (NumberFormatException nfe) {
//TODO:
}
}
else if(inputAsked == InputType.CARACTER)
{
//El dato pedido es un carácter
if(in.length() == 1)
{
try{
int inn =
(char)in.charAt(0);//Character.getNumericValue(in.charAt(0));
try{
computer.getState().setE(inn);
computer.getState().setRegisterChanged(ComputerRegister.E, true);
computer.getState().sendSignals();
}
catch (Exception xx)
{
//TODO:
}
}
catch (NumberFormatException nfe) {
//TODO:
}
}
else
{
//TODO: Error la cadena introducida es demasiado larga
(debería ser 1 solo carácter).
}
}
}
try{
if(executeSemisteps == false)
{
computer.executeNextInstruction();
}
else if(executeSemisteps == true)
{
if(computer.getSemistepInfo() == VirtualComputer.Last_Semistep)
{
computer.executeSemistep();
135
}
}
if(execTrace != null)
{
execTrace.registerStep(nextIns, computer.getState());
}
if(nextTime > 0)
{
nextTime = System.currentTimeMillis()-nextTime2+nextTime;
timeLabel.setText(addZeros(nextTime+"", 6) + " ms");
}
else if( startTime > 0)
{
timeLabel.setText(addZeros((System.currentTimeMillis()-startTime)+"",
6) + " ms");
}
}
catch(Exception excep)
{
}
setPidiendoDatos(InputType.FALSE);
}
else // Si no se ha pulsado ENTER, añadimos la entrada del teclado al buffer de entrada
{
inputBuffer += e.getKeyChar();
}
}
}
@Override
public void keyPressed(KeyEvent e) {
}
@Override
public void keyReleased(KeyEvent e) {
}
//Esta función es llamada cada vez que se pulsa una tecla mientras la consola esté enfocada.
@Override
public void keyTyped(KeyEvent e) {
displayInfo(e);
}
}
/**
*
* @brief Esta clase sirve para resaltar las posiciones de memoria que cambian en la JTable correspondiente
*
*/
class ColorCellRenderer extends DefaultTableCellRenderer{
JTable table; //Tabla a la que pertenecen las celdas
private int dir;
/**
*
*/
ColorCellRenderer(JTable t)
{
table = t;
dir = -1;
this.setHorizontalAlignment(RIGHT);
}
private static final long serialVersionUID = 1L;
@Override
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
Component cellComponent = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row,
column);
//cellComponent.setBackground(Color.WHITE);
if(row != dir && !isSelected)
{
cellComponent.setBackground(Color.WHITE);
}
else if(row == dir && !isSelected)
{
cellComponent.setBackground(new Color(0, 184, 245));
}
return cellComponent;
}
void restart(){
dir = -1;
table.repaint();
}
136
void flash(int row)
{
if (row >= 0 && row < table.getRowCount())
{
if(dir != row)
{
dir = row;
table.repaint();
}
}
}
}
/**
*
* @brief Versión de JLabel que sirve para marcar cuándo se usan las señales del computador
*
*/
class FlashySignal extends JLabel{
/**
*
*/
private static final long serialVersionUID = 1L;
FlashySignal(String s, Timer t){
super(s);
setForeground(Color.LIGHT_GRAY);
}
/**
* @brief Desmarca la señal
*/
public void restart()
{
setForeground(Color.LIGHT_GRAY);
}
/**
* Marca la señal
*/
public void flash(Color c)
{
//setForeground(new Color(0, 184, 245));
setForeground(c);
}
}
/**
* @brief Versión de JTextField que marca en azul cuando un registro es actualizado.
*/
class FlashyTextField extends JTextField{
/**
*
*/
private static final long serialVersionUID = 1L;
private Color baseBackground;
FlashyTextField(String text, Timer t)
{
super(text);
baseBackground = new Color(238,238, 238); //fondo gris
}
/**
* @brief Desmarca la señal
*/
public void restart()
{
setBackground(baseBackground);
}
/**
* Marca la señal
*/
public void flash(Color c)
{
if(getBackground() != c)
{
setBackground(c);
}
}
}
/**
* @detail Método que sirve para dar a conocer a la vista de depuración si
* el computador está a la espera de datos.
* @param b
*/
public void setPidiendoDatos(InputType b)
{
consolaListener.setPidiendoDatos(b);
}
137
/**
* @brief Método que cambia la base en que se muestran los datos
*/
public void setRegistersBase(Base b)
{
base = b;
if(base == Base.BINARY)
{
//En este caso mostramos CO y MD
textFieldCO.setBorder(textFieldA.getBorder());
textFieldMD.setBorder(textFieldA.getBorder());
coLabel.setForeground(Color.BLACK);
mdLabel.setForeground(Color.BLACK);
dLabel.setForeground(Color.BLACK);
}
else
{
//En este caso ocultamos CO y MD
textFieldCO.setBorder(BorderFactory.createLineBorder(new Color(238, 238, 238)));
textFieldMD.setBorder(BorderFactory.createLineBorder(new Color(238, 238, 238)));
coLabel.setForeground(new Color(238, 238, 238));
mdLabel.setForeground(new Color(238, 238, 238));
dLabel.setForeground(new Color(238, 238, 238));
}
updateJTableModel();
stateChanged();
}
/**
* Método que cambia el período de ejecución. Este cambio de período se notará la siguiente vez
* que se ejecute el código en modo "Ejecutar todo" o "Ejecutar hasta"
* @param millisecs
*/
public void setExecutionPeriod(long millisecs)
{
period = millisecs;
}
/**
* @detail Devuelve los datos del buffer de entrada del teclado
* @return
*/
public String getConsoleInput()
{
String r = null;
if(inputBuffer != null)
{
r = new String(inputBuffer);
}
inputBuffer = null;
return r;
}
/**
* @detail Añade el texto del parámetro text a la consola
* @param text
*/
public void addConsoleOutput(String text)
{
String s = consolaPane.getText();
s += text;
consolaPane.setText(s);
}
/**
* @brief Centra la tabla pTable en la posición indicada por el parámetro de entrada p
* @param p
*/
public void selectNextInstructionInMemoryNearP(int p)
{
int count = (int)pTable.getRowCount();
if(p >= 0 && p < count && count > 0)
{
pTable.setRowSelectionInterval(p, p);
int scrollTo = Math.min(p+7, count-1);
if(scrollTo >= 0 && scrollTo < count)
{
pTable.scrollRectToVisible(pTable.getCellRect(scrollTo, 0, true));
}
}
}
/**
* @detail Acción "Ejecutar Todo". Ejecuta las instrucciones del ordenador hasta llegar a un ALT,
* con la frecuencia del computador seleccionada.
*/
public void actionRun()
{
if(instructionTask == null)
{
//runMode = true;
if(isCheckBoxSelected == false)
138
{
executeSemisteps = false;
consolaListener.setPidiendoDatos(InputType.FALSE);
instructionTask = new ExecuteInstructionTask();
instructionTimer.scheduleAtFixedRate(instructionTask, 0, period);
startTime = System.currentTimeMillis();
nextTime = -1;
}
else if (isCheckBoxSelected == true)
{
executeSemisteps = true;
consolaListener.setPidiendoDatos(InputType.FALSE);
instructionTask = new ExecuteInstructionTask();
instructionTimer.scheduleAtFixedRate(instructionTask, 0, period/2);
startTime = System.currentTimeMillis();
nextTime = -1;
}
}
}
/**
* @detail Acción "Ejecutar Todo". Ejecuta las instrucciones del ordenador hasta llegar a cierta instrucción,
* o a un ALT, con la frecuencia del computador seleccionada.
*/
public void actionRunTo(int num)
{
actionPause();
if(instructionTask == null && num >= 0 && num <= Instruction.Memory_Address_Limit)
{
//runMode = true;
if(isCheckBoxSelected == false)
{
executeSemisteps = false;
runTo = num;
consolaListener.setPidiendoDatos(InputType.FALSE);
instructionTask = new ExecuteInstructionTask();
instructionTimer.scheduleAtFixedRate(instructionTask, 0, period);
startTime = System.currentTimeMillis();
nextTime = -1;
}
else if (isCheckBoxSelected == true)
{
executeSemisteps = true;
runTo = num;
consolaListener.setPidiendoDatos(InputType.FALSE);
instructionTask = new ExecuteInstructionTask();
instructionTimer.scheduleAtFixedRate(instructionTask, 0, period/2);
startTime = System.currentTimeMillis();
nextTime = -1;
}
}
}
/**
* @detail Acción Pausar. Detiene la ejecución de instrucciones.
*/
public void actionPause()
{
//runMode = false;
runTo = -1;
if(instructionTask != null)
{
instructionTask.cancel();
instructionTask = null;
}
}
/**
* @detail Acción Reiniciar. Reinicia el estado del computador.
*/
public void actionRestart()
{
if(execTrace != null)
{
execTrace.restart();
}
pTableRenderer.restart();
memoriaTableRenderer.restart();
runTo = -1;
if(instructionTask != null)
{
instructionTask.cancel();
instructionTask = null;
}
consolaPane.setText("");
startTime = -1;
nextTime = -1;
timeLabel.setText(addZeros("0", 6) + " ms");
try
{
computer.restart();
139
consolaListener.setPidiendoDatos(InputType.FALSE);
}
catch(Exception e)
{
}
}
/**
* @detail Acción Ejecutar siguiente instrucción. Solo ejecuta una instrucción.
*/
public void actionExecuteNextInstruction()
{
if(isCheckBoxSelected == false)
{
executeSemisteps = false;
}
else if (isCheckBoxSelected == true)
{
executeSemisteps = true;
}
executeNextInstruction();
}
public void executeNextInstruction()
{
pTableRenderer.restart();
memoriaTableRenderer.restart();
if(nextTime < 0)
{
nextTime = 0;
}
nextTime2 = System.currentTimeMillis();
if(executeSemisteps == false)
{
//Check if next instruction needs some kind of input.
Instruction.OperationCode op = computer.getNextInstruction().getOperationCode();
Instruction nextIns = new Instruction();
try{
nextIns.setInstructionSigned(computer.getNextInstruction().getDataSigned());
nextIns.setAddressLocation(computer.getNextInstruction().getAddressLocation());
} catch (Exception e)
{
}
if(op == Instruction.OperationCode.LCA || op == Instruction.OperationCode.LCAI )
{
/*
* In that case the instruction will be executed when when we get the input.
*/
setPidiendoDatos(InputType.CARACTER);
}
else if(op == Instruction.OperationCode.LEE || op == Instruction.OperationCode.LEEI)
{
/*
* In that case the instruction will be executed when when we get the input.
*/
setPidiendoDatos(InputType.NUMBER);
}
else{
//If it's not needed, execute instruction.
if(op == Instruction.OperationCode.ALT)
{
actionPause();
nextTime = System.currentTimeMillis()-nextTime2+nextTime;
timeLabel.setText(addZeros(nextTime+"", 6) + " ms");
}
else
{
try{
computer.executeNextInstruction();
if(execTrace != null)
{
execTrace.registerStep(nextIns, computer.getState());
}
nextTime = System.currentTimeMillis()-nextTime2+nextTime;
timeLabel.setText(addZeros(nextTime+"", 6) + " ms");
}
catch(Exception e)
{
//TODO: Catch exception
}
}
}
}
else if (executeSemisteps == true)
{
if(computer.getSemistepInfo() == VirtualComputer.First_Semistep)
{
try{
computer.executeSemistep();
140
}
catch (Exception e)
{
}
}
else if(computer.getSemistepInfo() == VirtualComputer.Last_Semistep)
{
//Check if next instruction needs some kind of input.
Instruction.OperationCode op = computer.getNextInstruction().getOperationCode();
Instruction nextIns = new Instruction();
try{
nextIns.setInstructionSigned(computer.getNextInstruction().getDataSigned());
nextIns.setAddressLocation(computer.getNextInstruction().getAddressLocation());
} catch (Exception e)
{
}
if(op == Instruction.OperationCode.LCA || op == Instruction.OperationCode.LCAI )
{
/*
* In that case the instruction will be executed when when we get the input.
*/
setPidiendoDatos(InputType.CARACTER);
}
else if(op == Instruction.OperationCode.LEE || op == Instruction.OperationCode.LEEI)
{
/*
* In that case the instruction will be executed when when we get the input.
*/
setPidiendoDatos(InputType.NUMBER);
}
else{
//If it's not needed, execute instruction.
if(op == Instruction.OperationCode.ALT)
{
actionPause();
nextTime = System.currentTimeMillis()-nextTime2+nextTime;
timeLabel.setText(addZeros(nextTime+"", 6) + " ms");
}
else
{
try{
computer.executeSemistep();
if(execTrace != null)
{
execTrace.registerStep(nextIns, computer.getState());
}
nextTime = System.currentTimeMillis()-nextTime2+nextTime;
timeLabel.setText(addZeros(nextTime+"", 6) + " ms");
}
catch(Exception e)
{
//TODO: Catch exception
}
}
}
}
}
}
/**
* @detail Cuando cierta posición de memoria cambia, este método es llamado para actualizar
* la fila adecuada de tabla de memoria de la interfaz gráfica.
*/
public void changeMemoryAddress(Instruction i) throws IndexOutOfBoundsException
{
int ma = i.getAddressLocation();
DefaultTableModel tModel = (DefaultTableModel) pTable.getModel();
DefaultTableModel mModel = (DefaultTableModel) memoriaTable.getModel();
if(ma >= 0 && ma < tModel.getRowCount())
{
//colorRenderer.flash(memoriaTable, ma, changesTimer);
if(i.isInstruction())
{
tModel.setValueAt(Integer.toString(ma), ma, 0);
tModel.setValueAt(i.getOperationCode().name(), ma, 1);
tModel.setValueAt(Integer.toString(i.getInstructionOperator()), ma, 2);
if(base == Base.DECIMAL)
{
tModel.setValueAt(Integer.toString(i.getDataSigned()), ma, 3);
mModel.setValueAt(Integer.toString(i.getDataSigned()), ma, 3);
}
else if(base == Base.BINARY)
{
tModel.setValueAt(addZeros(Integer.toString(i.getDataUnsigned(), 2), 16), ma, 3);
mModel.setValueAt(addZeros(Integer.toString(i.getDataUnsigned(), 2), 16), ma, 3);
}
else if(base == Base.HEXADECIMAL)
141
{
}
}
else
{
tModel.setValueAt(addZeros(Integer.toString(i.getDataUnsigned(), 16), 4), ma, 3);
mModel.setValueAt(addZeros(Integer.toString(i.getDataUnsigned(), 16), 4), ma, 3);
mModel.setValueAt(Integer.toString(ma), ma, 0);
mModel.setValueAt(i.getOperationCode().name(), ma, 1);
mModel.setValueAt(Integer.toString(i.getInstructionOperator()), ma, 2);
tModel.setValueAt(Integer.toString(ma), ma, 0);
tModel.setValueAt("", ma, 1);
tModel.setValueAt("", ma, 2);
if(base == Base.DECIMAL)
{
tModel.setValueAt(Integer.toString(i.getDataSigned()), ma, 3);
mModel.setValueAt(Integer.toString(i.getDataSigned()), ma, 3);
}
else if(base == Base.BINARY)
{
tModel.setValueAt(addZeros(Integer.toString(i.getDataUnsigned(),
mModel.setValueAt(addZeros(Integer.toString(i.getDataUnsigned(),
}
else if(base == Base.HEXADECIMAL)
{
tModel.setValueAt(addZeros(Integer.toString(i.getDataUnsigned(),
mModel.setValueAt(addZeros(Integer.toString(i.getDataUnsigned(),
}
mModel.setValueAt(Integer.toString(ma), ma, 0);
mModel.setValueAt("", ma, 1);
mModel.setValueAt("", ma, 2);
}
}
else
{
throw new IndexOutOfBoundsException(i.toString());
}
}
/**
* @detail Cuando muchas posiciones de memoria cambian, este método es llamado para actualizar
* la tabla de memorian entera de la interfaz gráfica.
*/
private void updateJTableModel()
{
String[] columnas = {"Dirección","Instrucción", "Operador", "Dato" };
DefaultTableModel tModel = (new DefaultTableModel()
{
/**
*
*/
private static final long serialVersionUID = 1L;
public boolean isCellEditable(int rowIndex, int colIndex) {
return false;
}
});
DefaultTableModel mModel = (new DefaultTableModel()
{
/**
*
*/
private static final long serialVersionUID = 1L;
public boolean isCellEditable(int rowIndex, int colIndex) {
return false;
}
});
pTable.setModel(tModel);
memoriaTable.setModel(mModel);
tModel.setColumnIdentifiers(columnas);
mModel.setColumnIdentifiers(columnas);
DefaultTableCellRenderer rightRenderer = new DefaultTableCellRenderer();
rightRenderer.setHorizontalAlignment( DefaultTableCellRenderer.RIGHT );
pTable.getColumnModel().getColumn(3).setCellRenderer( rightRenderer );
pTable.getColumnModel().getColumn(0).setMaxWidth(80);
pTable.getColumnModel().getColumn(1).setMaxWidth(80);
pTable.getColumnModel().getColumn(2).setMaxWidth(80);
memoriaTable.getColumnModel().getColumn(3).setCellRenderer( rightRenderer );
memoriaTable.getColumnModel().getColumn(0).setMaxWidth(80);
memoriaTable.getColumnModel().getColumn(1).setMaxWidth(80);
memoriaTable.getColumnModel().getColumn(2).setMaxWidth(80);
DefaultTableCellRenderer centerRenderer = new DefaultTableCellRenderer();
centerRenderer.setHorizontalAlignment( DefaultTableCellRenderer.CENTER );
142
2), 16), ma, 3);
2), 16), ma, 3);
16), 4), ma, 3);
16), 4), ma, 3);
pTable.getColumnModel().getColumn(2).setCellRenderer( centerRenderer );
memoriaTable.getColumnModel().getColumn(2).setCellRenderer( centerRenderer );
pTable.getColumnModel().getColumn(1).setCellRenderer( centerRenderer );
memoriaTable.getColumnModel().getColumn(1).setCellRenderer( centerRenderer );
pTable.getColumnModel().getColumn(0).setCellRenderer( centerRenderer );
memoriaTable.getColumnModel().getColumn(0).setCellRenderer( centerRenderer );
Vector<String> line;
for(Instruction i: computer.getMemoryMap())
{
line = new Vector<String>();
if(i.isInstruction() == true)
{
line.add(Integer.toString(i.getAddressLocation()));
line.add(i.getOperationCode().name());
line.add(Integer.toString(i.getInstructionOperator()));
if(base == Base.DECIMAL)
{
line.add(Integer.toString(i.getDataSigned()));
}
else if(base == Base.BINARY)
{
line.add(addZeros(Integer.toString(i.getDataUnsigned(), 2), 16) );
}
else if(base == Base.HEXADECIMAL)
{
line.add(addZeros(Integer.toString(i.getDataUnsigned(), 16), 4) );
}
}
else
{
line.add(Integer.toString(i.getAddressLocation()));
line.add("");
line.add("");
if(base == Base.DECIMAL)
{
line.add(Integer.toString(i.getDataSigned()));
}
else if(base == Base.BINARY)
{
line.add(addZeros(Integer.toString(i.getDataUnsigned(), 2), 16) );
}
else if(base == Base.HEXADECIMAL)
{
line.add(addZeros(Integer.toString(i.getDataUnsigned(), 16),4) );
}
}
tModel.addRow(line);
mModel.addRow(line);
//System.out.println(i);
}
pTableRenderer = new ColorCellRenderer(pTable);
memoriaTableRenderer = new ColorCellRenderer(memoriaTable);
pTable.getColumnModel().getColumn(3).setCellRenderer(pTableRenderer);
pTable.getColumnModel().getColumn(2).setCellRenderer(pTableRenderer);
pTable.getColumnModel().getColumn(1).setCellRenderer(pTableRenderer);
pTable.getColumnModel().getColumn(0).setCellRenderer(pTableRenderer);
memoriaTable.getColumnModel().getColumn(3).setCellRenderer(memoriaTableRenderer);
memoriaTable.getColumnModel().getColumn(2).setCellRenderer(memoriaTableRenderer);
memoriaTable.getColumnModel().getColumn(1).setCellRenderer(memoriaTableRenderer);
memoriaTable.getColumnModel().getColumn(0).setCellRenderer(memoriaTableRenderer);
}
/**
* @brief Inicializa la memoria del computador con cierto código
* @param codeArray Código a depurar
*/
public void setDebugCode(ArrayList<Instruction> codeArray, File file)
{
actionRestart();
debugFile = file;
execTrace = new Trace(debugFile);
computer.setMemoryMap(codeArray);
updateJTableModel();
selectNextInstructionInMemoryNearP(0);
}
/**
* Constructor de la vista depuración.
*/
public DebugViewManager()
{
super();
//Inicializar algunas variables de la clase.
isCheckBoxSelected = executeSemisteps = false;
execTrace = null;
debugFile = null;
143
pTableRenderer = null;
memoriaTableRenderer = null;
startTime = -1;
nextTime = -1;
instructionTimer = new Timer("Timer");
changesTimer = new Timer("Changes");
instructionTask = null;
//runMode = false;
runTo = -1;
setOrientation(JSplitPane.HORIZONTAL_SPLIT);
setResizeWeight(0);
setDividerLocation(630);
//Queremos que la barra de separación no se pueda mover
addPropertyChangeListener(JSplitPane.DIVIDER_LOCATION_PROPERTY, new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent pce) {
// do here
setDividerLocation(630);
}
});
//Inicializamos el computador
computer = new VirtualComputer();
computer.setListener(this);
//Período inicial de 500ms
period = 500L;
//JSplitPlane que contiene el visor de memoria entorno a P y el visor general de memoria
JSplitPane memoryViewers= new JSplitPane();
memoryViewers.setOrientation(JSplitPane.VERTICAL_SPLIT);
memoryViewers.setDividerLocation(300);
setRightComponent(memoryViewers);
JTabbedPane nearPViewer = new JTabbedPane(JTabbedPane.TOP);
nearPViewer.setMinimumSize(new Dimension(417, 300));
JScrollPane scrollNearP = new JScrollPane();
nearPViewer.addTab("Memoria entorno a P", null, scrollNearP, null);
JTabbedPane allMemoryViewer = new JTabbedPane(JTabbedPane.TOP);
JScrollPane scrollAllMemory = new JScrollPane();
allMemoryViewer.addTab("Visor de Memoria", null, scrollAllMemory, null);
memoryViewers.setLeftComponent(nearPViewer);
memoryViewers.setRightComponent(allMemoryViewer);
//Tabla de memoria del visor de memoria entorno a P
pTable = new JTable(new DefaultTableModel()
{
/**
*
*/
private static final long serialVersionUID = 1L;
public boolean isCellEditable(int rowIndex, int colIndex) {
return false;
}
});
//El usuario solo debería poder seleccionar una fila/instrucción.
ListSelectionModel psm = pTable.getSelectionModel();
psm.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
TableListener tl = new TableListener();
psm.addListSelectionListener(tl);
scrollNearP.setViewportView(pTable);
//Aquí inicializamos todos los campos de los registros
textFieldA = new FlashyTextField("0", changesTimer);
textFieldA.setColumns(12);
textFieldA.setHorizontalAlignment(JTextField.RIGHT);
textFieldA.setEditable(false);
textFieldP = new FlashyTextField("0", changesTimer);
textFieldP.setColumns(8);
textFieldP.setHorizontalAlignment(JTextField.RIGHT);
textFieldP.setEditable(false);
textFieldS = new FlashyTextField("0", changesTimer);
textFieldS.setColumns(8);
textFieldS.setHorizontalAlignment(JTextField.RIGHT);
textFieldS.setEditable(false);
textFieldI = new FlashyTextField("0", changesTimer);
textFieldI.setColumns(8);
textFieldI.setHorizontalAlignment(JTextField.RIGHT);
textFieldI.setEditable(false);
textFieldT = new FlashyTextField("0", changesTimer);
textFieldT.setColumns(12);
144
textFieldT.setHorizontalAlignment(JTextField.RIGHT);
textFieldT.setEditable(false);
textFieldE = new FlashyTextField("0", changesTimer);
textFieldE.setColumns(12);
textFieldE.setHorizontalAlignment(JTextField.RIGHT);
textFieldE.setEditable(false);
textFieldCO = new FlashyTextField("0000", changesTimer);
textFieldCO.setColumns(3);
textFieldCO.setHorizontalAlignment(JTextField.RIGHT);
textFieldCO.setEditable(false);
textFieldMD = new FlashyTextField("0", changesTimer);
textFieldMD.setColumns(1);
textFieldMD.setHorizontalAlignment(JTextField.RIGHT);
textFieldMD.setEditable(false);
//tabbedMonitor es la pantalla de la consola
JTabbedPane tabbedMonitor = new JTabbedPane(JTabbedPane.TOP);
JScrollPane scrollMonitor = new JScrollPane();
tabbedMonitor.addTab("Monitor", null, scrollMonitor, null);
consolaPane = new JTextPane();
consolaPane.setEditable(false);
//Con esto el enter será sólo un carácter raro sin efecto
consolaPane.setFocusTraversalKeysEnabled(false);
consolaListener = new ConsoleKeyListener();
consolaPane.addKeyListener(consolaListener);
scrollMonitor.setViewportView(consolaPane);
//A continuación cargamos todos los iconos que necesitamos
java.net.URL imageURL = Emulator.class.getResource("images/bus.png");
ImageIcon icon = new ImageIcon(imageURL);
JLabel busLabel = new JLabel();
busLabel.setIcon(icon);
imageURL = Emulator.class.getResource("images/ALU.png");
icon = new ImageIcon(imageURL);
JLabel aluLabel = new JLabel();
aluLabel.setIcon(icon);
imageURL = Emulator.class.getResource("images/sBus.png");
icon = new ImageIcon(imageURL);
JLabel sBusLabel = new JLabel();
sBusLabel.setIcon(icon);
imageURL = Emulator.class.getResource("images/keyboard-icon2.png");
icon = new ImageIcon(imageURL);
JLabel keyboardButton = new JLabel();
keyboardButton.setIcon(icon);
//Los siguientes iconos no serán visibles, son un hack para poder pintar correctamente las flechas
//que conectan los registros
imageURL = Emulator.class.getResource("images/point.png");
icon = new ImageIcon(imageURL);
JLabel point = new JLabel();
point.setIcon(icon);
JLabel point2 = new JLabel();
point2.setIcon(icon);
point2.setVisible(false);
JLabel point3 = new JLabel();
point3.setIcon(icon);
point3.setVisible(false);
JLabel point4 = new JLabel();
point4.setIcon(icon);
point4.setVisible(false);
JLabel point5 = new JLabel();
point5.setIcon(icon);
point5.setVisible(false);
//Estos puntos son las válvulas de control de flujo que manejan las señales del computador
imageURL = Emulator.class.getResource("images/punto.png");
icon = new ImageIcon(imageURL);
JLabel punto1 = new JLabel();
punto1.setIcon(icon);
JLabel punto2 = new JLabel();
punto2.setIcon(icon);
JLabel punto3 = new JLabel();
punto3.setIcon(icon);
JLabel punto4 = new JLabel();
punto4.setIcon(icon);
JLabel punto5 = new JLabel();
punto5.setIcon(icon);
JLabel punto6 = new JLabel();
punto6.setIcon(icon);
JLabel punto7 = new JLabel();
punto7.setIcon(icon);
JLabel punto8 = new JLabel();
145
punto8.setIcon(icon);
JLabel punto9 = new JLabel();
punto9.setIcon(icon);
JLabel punto10 = new JLabel();
punto10.setIcon(icon);
JLabel punto11 = new JLabel();
punto11.setIcon(icon);
JLabel punto12 = new JLabel();
punto12.setIcon(icon);
JLabel punto13 = new JLabel();
punto13.setIcon(icon);
JLabel punto14 = new JLabel();
punto14.setIcon(icon);
//JButton keyboardButton = new JButton("Abrir Teclado Virtual");
//Etiquetas de los registros
JLabel eLabel = new JLabel("E");
JLabel tLabel = new JLabel("T");
JLabel aLabel = new JLabel("A");
JLabel pLabel = new JLabel("P");
JLabel sLabel = new JLabel("S");
JLabel iLabel = new JLabel("I");
JLabel mLabel = new JLabel("M");
JLabel ssLabel = new JLabel("S");
coLabel = new JLabel("CO");
mdLabel = new JLabel("MD");
dLabel = new JLabel("D");
//Etiquetas de las señales
etLabel = new FlashySignal("ET", changesTimer);
stLabel = new FlashySignal("ST", changesTimer);
eeLabel = new FlashySignal("EE", changesTimer);
seLabel = new FlashySignal("SE", changesTimer);
escpLabel = new FlashySignal("ESCP", changesTimer);
leetLabel = new FlashySignal("LEET", changesTimer);
eaLabel = new FlashySignal("EA", changesTimer);
saLabel = new FlashySignal("SA", changesTimer);
eoLabel = new FlashySignal("EO", changesTimer);
sumaLabel = new FlashySignal("SUMA", changesTimer);
resaLabel = new FlashySignal("RESA", changesTimer);
multaLabel = new FlashySignal("MULTA", changesTimer);
incpLabel = new FlashySignal("INCP", changesTimer);
spLabel = new FlashySignal("SP", changesTimer);
epLabel = new FlashySignal("EP", changesTimer);
sdLabel = new FlashySignal("SD", changesTimer);
eiLabel = new FlashySignal("EI", changesTimer);
esLabel = new FlashySignal("ES", changesTimer);
lecmLabel = new FlashySignal("LECM", changesTimer);
escmLabel = new FlashySignal("ESCM", changesTimer);
divaLabel = new FlashySignal("DIVA", changesTimer);
modaLabel = new FlashySignal("MODA", changesTimer);
//computerGraphics es el panel donde se dibujará el esquema del computador
//Es de tipo ConnectorContainer para poder pintar flechas fácilmente en él
ConnectorContainer computerGraphics = new ConnectorContainer();
computerGraphics.setMinimumSize(new Dimension(630, 400));
computerGraphics.setMaximumSize(new Dimension(630, Short.MAX_VALUE));
setLeftComponent(computerGraphics);
//Layout del computador
GroupLayout gl_menu2 = new GroupLayout(computerGraphics);
gl_menu2.setHorizontalGroup(
gl_menu2.createParallelGroup(Alignment.LEADING)
.addGroup(gl_menu2.createSequentialGroup()
.addContainerGap(10, 10)
.addGroup(gl_menu2.createParallelGroup(Alignment.LEADING)
.addGroup(gl_menu2.createSequentialGroup()
.addComponent(aLabel,
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addContainerGap(10, 10)
.addComponent(textFieldA,
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
)
.addGroup(gl_menu2.createSequentialGroup()
.addContainerGap(72, 72)
.addComponent(punto7,
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addContainerGap(20, 20)
.addComponent(eaLabel,
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
)
.addGroup(gl_menu2.createSequentialGroup()
.addContainerGap(40, 40)
.addComponent(aluLabel,
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addContainerGap(20, 20)
.addGroup(gl_menu2.createParallelGroup(A
lignment.LEADING)
.addComponent(sumaLa
bel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addComponent(resaLa
146
bel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addComponent(multaL
abel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addComponent(divaLa
bel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
bel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE,
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE,
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE,
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE,
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE,
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE,
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE,
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE,
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE,
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE,
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE,
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE,
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE,
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE,
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE,
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE,
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE,
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE,
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE,
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE,
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE,
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE,
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE,
.addComponent(modaLa
)
)
.addGroup(gl_menu2.createSequentialGroup()
.addContainerGap(54, 54)
.addComponent(point,
GroupLayout.PREFERRED_SIZE)
)
.addGroup(gl_menu2.createSequentialGroup()
.addContainerGap(26, 26)
.addComponent(punto8,
GroupLayout.PREFERRED_SIZE)
.addContainerGap(20, 20)
.addComponent(saLabel,
GroupLayout.PREFERRED_SIZE)
.addContainerGap(23, 23)
.addComponent(punto9,
GroupLayout.PREFERRED_SIZE)
.addContainerGap(20, 20)
.addComponent(eoLabel,
GroupLayout.PREFERRED_SIZE)
.addContainerGap(30, 30)
.addComponent(mLabel,
GroupLayout.PREFERRED_SIZE)
)
)
.addContainerGap(90, 90)
.addGroup(gl_menu2.createParallelGroup(Alignment.LEADING)
.addGroup(gl_menu2.createSequentialGroup()
.addComponent(pLabel,
GroupLayout.PREFERRED_SIZE)
.addContainerGap(10, 10)
.addComponent(textFieldP,
GroupLayout.PREFERRED_SIZE)
.addContainerGap(10, 10)
.addComponent(incpLabel,
GroupLayout.PREFERRED_SIZE)
)
.addGroup(gl_menu2.createSequentialGroup()
.addComponent(epLabel,
GroupLayout.PREFERRED_SIZE)
.addContainerGap(20, 20)
.addComponent(punto10,
GroupLayout.PREFERRED_SIZE)
.addContainerGap(25, 25)
.addComponent(punto11,
GroupLayout.PREFERRED_SIZE)
.addContainerGap(20, 20)
.addComponent(spLabel,
GroupLayout.PREFERRED_SIZE)
.addContainerGap(20, 20)
.addComponent(ssLabel,
GroupLayout.PREFERRED_SIZE)
.addContainerGap(42, 42)
.addComponent(esLabel,
GroupLayout.PREFERRED_SIZE)
)
.addGroup(gl_menu2.createSequentialGroup()
.addComponent(sBusLabel,
GroupLayout.PREFERRED_SIZE)
.addContainerGap(10, 10)
.addComponent(punto12,
GroupLayout.PREFERRED_SIZE)
.addContainerGap(10, 10)
.addComponent(textFieldS,
GroupLayout.PREFERRED_SIZE)
.addContainerGap(10, 10)
.addComponent(sLabel,
GroupLayout.PREFERRED_SIZE)
.addContainerGap(24, 24)
.addComponent(point4,
GroupLayout.PREFERRED_SIZE)
)
.addGroup(gl_menu2.createSequentialGroup()
.addContainerGap(70, 70)
.addComponent(sdLabel,
GroupLayout.PREFERRED_SIZE)
.addContainerGap(20, 20)
.addComponent(punto13,
GroupLayout.PREFERRED_SIZE)
)
.addGroup(gl_menu2.createSequentialGroup()
.addComponent(coLabel,
GroupLayout.PREFERRED_SIZE)
147
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addContainerGap(15, 15)
.addComponent(mdLabel,
.addContainerGap(15, 15)
.addComponent(dLabel,
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
)
.addGroup(gl_menu2.createSequentialGroup()
.addComponent(textFieldCO,
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addContainerGap(1, 1)
.addComponent(textFieldMD,
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addContainerGap(1, 1)
.addComponent(textFieldI,
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addContainerGap(15, 15)
.addComponent(iLabel,
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
)
.addGroup(gl_menu2.createSequentialGroup()
.addContainerGap(280, 280)
.addComponent(lecmLabel,
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addContainerGap(20, 20)
.addComponent(point2,
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
)
.addGroup(gl_menu2.createSequentialGroup()
.addContainerGap(280, 280)
.addComponent(escmLabel,
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addContainerGap(20, 20)
.addComponent(point3,
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
)
.addGroup(gl_menu2.createSequentialGroup()
.addContainerGap(80, 80)
.addComponent(eiLabel,
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addContainerGap(20, 20)
.addComponent(punto14,
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
)
)
)
.addComponent(busLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE,
GroupLayout.PREFERRED_SIZE)
.addGroup(gl_menu2.createSequentialGroup()
.addContainerGap(10, 10)
.addGroup(gl_menu2.createParallelGroup(Alignment.LEADING)
.addGroup(gl_menu2.createSequentialGroup()
.addGroup(gl_menu2.createParallelGroup(A
lignment.LEADING)
.addGroup(gl_menu2.createSeque
ntialGroup()
.addContai
nerGap(20, 20)
.addCompon
ent(eeLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addContai
nerGap(20, 20)
.addCompon
ent(punto3, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addContai
nerGap(40, 40)
.addCompon
ent(seLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addContai
nerGap(20, 20)
.addCompon
ent(punto4, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
)
.addGroup(gl_menu2.createSeque
ntialGroup()
.addCompon
ent(eLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addContai
nerGap(10, 10)
.addCompon
ent(textFieldE, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
)
)
.addContainerGap(280, 280)
.addGroup(gl_menu2.createParallelGroup(A
lignment.LEADING)
.addGroup(
gl_menu2.createSequentialGroup()
.addComponent(etLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addContainerGap(20, 20)
148
.addComponent(punto1, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addContainerGap(40, 40)
.addComponent(stLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addContainerGap(20, 20)
.addComponent(punto2, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
)
.addGroup(
gl_menu2.createSequentialGroup()
.addComponent(tLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addContainerGap(10, 10)
.addComponent(textFieldT, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addContainerGap(10, 10)
.addComponent(point5, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
)
)
)
.addGroup(gl_menu2.createSequentialGroup()
.addGroup(gl_menu2.createSequentialGroup()
.addCompon
ent(leetLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addCompon
ent(punto6, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
)
.addContainerGap(5, 5)
.addGroup(gl_menu2.createParallelGroup(Alignment.
LEADING)
.addGroup(gl_menu2.createSeque
ntialGroup()
.addCompon
ent(escpLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addContai
nerGap(20, 20)
.addCompon
ent(punto5, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
)
.addComponent(tabbedMonitor,
0, 400, 400)
)
)
.addGroup(gl_menu2.createSequentialGroup()
.addContainerGap(20, 20)
.addComponent(keyboardButton,
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
)
)
)
);
gl_menu2.setVerticalGroup(
gl_menu2.createSequentialGroup()
.addContainerGap(10, 10)
.addGroup(gl_menu2.createParallelGroup(Alignment.LEADING)
.addGroup(gl_menu2.createSequentialGroup()
.addContainerGap(7, 7)
.addGroup(gl_menu2.createParallelGroup(Alignment.LEADING)
.addComponent(aLabel,
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addComponent(textFieldA,
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
)
.addContainerGap(10, 10)
.addGroup(gl_menu2.createParallelGroup(Alignment.CENTER)
.addComponent(punto7,
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addComponent(eaLabel,
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
)
.addContainerGap(10, 10)
.addGroup(gl_menu2.createParallelGroup(Alignment.LEADING)
.addComponent(aluLabel,
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addGroup(gl_menu2.createSequentialGroup
()
.addComponent(sumaLa
bel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addComponent(resaLa
bel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addComponent(multaL
abel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addComponent(divaLa
bel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addComponent(modaLa
149
bel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE,
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE,
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE,
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE,
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE,
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE,
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE,
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE,
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE,
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE,
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE,
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE,
)
)
.addContainerGap(20, 20)
.addComponent(point, GroupLayout.PREFERRED_SIZE,
.addContainerGap(10, 10)
.addGroup(gl_menu2.createParallelGroup(Alignment.CENTER)
.addComponent(punto8,
GroupLayout.PREFERRED_SIZE)
.addComponent(saLabel,
GroupLayout.PREFERRED_SIZE)
.addComponent(punto9,
GroupLayout.PREFERRED_SIZE)
.addComponent(eoLabel,
GroupLayout.PREFERRED_SIZE)
.addComponent(mLabel,
GroupLayout.PREFERRED_SIZE)
)
)
.addGroup(gl_menu2.createSequentialGroup()
.addGroup(gl_menu2.createParallelGroup(Alignment.CENTER)
.addComponent(pLabel,
GroupLayout.PREFERRED_SIZE)
.addComponent(textFieldP,
GroupLayout.PREFERRED_SIZE)
.addComponent(incpLabel,
GroupLayout.PREFERRED_SIZE)
)
.addContainerGap(10, 10)
.addGroup(gl_menu2.createParallelGroup(Alignment.CENTER)
.addComponent(epLabel,
GroupLayout.PREFERRED_SIZE)
.addComponent(punto10,
GroupLayout.PREFERRED_SIZE)
.addComponent(punto11,
GroupLayout.PREFERRED_SIZE)
.addComponent(spLabel,
GroupLayout.PREFERRED_SIZE)
.addGroup(gl_menu2.createSequentialGroup
()
.addContainerGap(15,
15)
l, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE,
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE,
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE,
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE,
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE,
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE,
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE,
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE,
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE,
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE,
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE,
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE,
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE,
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE,
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE,
.addComponent(ssLabe
)
.addComponent(esLabel,
)
.addGroup(gl_menu2.createParallelGroup(Alignment.CENTER)
.addComponent(sBusLabel,
GroupLayout.PREFERRED_SIZE)
.addComponent(punto12,
GroupLayout.PREFERRED_SIZE)
.addComponent(textFieldS,
GroupLayout.PREFERRED_SIZE)
.addComponent(sLabel,
GroupLayout.PREFERRED_SIZE)
.addComponent(point4,
GroupLayout.PREFERRED_SIZE)
)
.addContainerGap(5, 5)
.addGroup(gl_menu2.createParallelGroup(Alignment.CENTER)
.addComponent(sdLabel,
GroupLayout.PREFERRED_SIZE)
.addComponent(punto13,
GroupLayout.PREFERRED_SIZE)
)
.addContainerGap(1, 1)
.addGroup(gl_menu2.createParallelGroup(Alignment.LEADING)
.addComponent(coLabel,
GroupLayout.PREFERRED_SIZE)
.addComponent(mdLabel,
GroupLayout.PREFERRED_SIZE)
.addComponent(dLabel,
GroupLayout.PREFERRED_SIZE)
)
.addGroup(gl_menu2.createParallelGroup(Alignment.LEADING)
.addComponent(textFieldCO,
GroupLayout.PREFERRED_SIZE)
.addComponent(textFieldMD,
GroupLayout.PREFERRED_SIZE)
.addComponent(textFieldI,
GroupLayout.PREFERRED_SIZE)
.addComponent(iLabel,
GroupLayout.PREFERRED_SIZE)
)
.addGroup(gl_menu2.createParallelGroup(Alignment.CENTER)
.addComponent(lecmLabel,
GroupLayout.PREFERRED_SIZE)
150
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
)
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE,
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE,
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE,
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE,
GroupLayout.PREFERRED_SIZE)
lignment.CENTER)
.addComponent(point2,
.addGroup(gl_menu2.createParallelGroup(Alignment.CENTER)
.addComponent(escmLabel,
GroupLayout.PREFERRED_SIZE)
.addComponent(point3,
GroupLayout.PREFERRED_SIZE)
)
.addGroup(gl_menu2.createParallelGroup(Alignment.CENTER)
.addComponent(eiLabel,
GroupLayout.PREFERRED_SIZE)
.addComponent(punto14,
GroupLayout.PREFERRED_SIZE)
)
.addContainerGap(2, 2)
)
)
.addComponent(busLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE,
.addGroup(gl_menu2.createSequentialGroup()
.addContainerGap(10, 10)
.addGroup(gl_menu2.createParallelGroup(Alignment.CENTER)
.addGroup(gl_menu2.createSequentialGroup()
.addGroup(gl_menu2.createParallelGroup(A
.addComponent(eeLabe
l, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addComponent(punto3
, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addComponent(seLabe
l, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
lignment.LEADING)
.addComponent(punto4
)
.addContainerGap(10, 10)
.addGroup(gl_menu2.createParallelGroup(A
.addComponent(eLabel
, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
eldE, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addComponent(textFi
)
)
.addGroup(gl_menu2.createSequentialGroup()
.addGroup(gl_menu2.createParallelGroup(A
lignment.CENTER)
.addComponent(etLabe
l, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addComponent(punto1
, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addComponent(stLabe
l, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
lignment.CENTER)
.addComponent(punto2
)
.addContainerGap(10, 10)
.addGroup(gl_menu2.createParallelGroup(A
.addComponent(tLabel
, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addComponent(textFi
eldT, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addComponent(point5
, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
)
)
)
)
.addGroup(gl_menu2.createParallelGroup(Alignment.LEADING)
.addGroup(gl_menu2.createSequentialGroup()
.addContainerGap(10, 10)
.addGroup(gl_menu2.createParallelGroup(Alignment.CENTER)
.addComponent(leetLabel, GroupLayout.PREFERRED_SIZE,
GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addComponent(punto6, GroupLayout.PREFERRED_SIZE,
GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
)
)
.addGroup(gl_menu2.createSequentialGroup()
.addContainerGap(10, 10)
.addGroup(gl_menu2.createParallelGroup(Alignment.CENTER)
.addComponent(escpLabel,
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addComponent(punto5,
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
)
.addContainerGap(10, 10)
.addComponent(tabbedMonitor, 0, 300, 300)
151
GroupLayout.PREFERRED_SIZE)
)
)
.addContainerGap(10, 10)
.addComponent(keyboardButton, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE,
);
computerGraphics.setLayout(gl_menu2);
//Lista de flechas del esquema del computador
ArrayList<JConnector> con = new ArrayList<JConnector>();
con.add( new JConnector(etLabel ,punto1, ConnectLine.LINE_ARROW_DEST,
ConnectLine.LINE_TYPE_RECT_HORIZONTAL, Color.BLACK));
con.add( new JConnector(punto1 ,textFieldT, ConnectLine.LINE_ARROW_DEST,
ConnectLine.LINE_TYPE_RECT_VERTICAL, Color.BLACK));
con.add(new JConnector(punto1 ,busLabel, ConnectLine.LINE_ARROW_SOURCE,
ConnectLine.LINE_TYPE_RECT_VERTICAL, Color.BLACK));
con.add( new JConnector(stLabel ,punto2, ConnectLine.LINE_ARROW_DEST,
ConnectLine.LINE_TYPE_RECT_HORIZONTAL, Color.BLACK));
con.add( new JConnector(punto2 ,textFieldT, ConnectLine.LINE_ARROW_SOURCE,
ConnectLine.LINE_TYPE_RECT_VERTICAL, Color.BLACK));
con.add( new JConnector(punto2 ,busLabel, ConnectLine.LINE_ARROW_DEST,
ConnectLine.LINE_TYPE_RECT_VERTICAL, Color.BLACK));
con.add( new JConnector(sLabel ,point4, ConnectLine.LINE_ARROW_DEST,
ConnectLine.LINE_TYPE_RECT_HORIZONTAL, Color.BLACK));
///////
con.add( new JConnector(eeLabel ,punto3, ConnectLine.LINE_ARROW_DEST,
ConnectLine.LINE_TYPE_RECT_HORIZONTAL, Color.BLACK));
con.add( new JConnector(punto3 ,textFieldE, ConnectLine.LINE_ARROW_DEST,
ConnectLine.LINE_TYPE_RECT_VERTICAL, Color.BLACK));
con.add(new JConnector(punto3 ,busLabel, ConnectLine.LINE_ARROW_SOURCE,
ConnectLine.LINE_TYPE_RECT_VERTICAL, Color.BLACK));
con.add( new JConnector(seLabel ,punto4, ConnectLine.LINE_ARROW_DEST,
ConnectLine.LINE_TYPE_RECT_HORIZONTAL, Color.BLACK));
con.add( new JConnector(punto4 ,textFieldE, ConnectLine.LINE_ARROW_SOURCE,
ConnectLine.LINE_TYPE_RECT_VERTICAL, Color.BLACK));
con.add( new JConnector(punto4 ,busLabel, ConnectLine.LINE_ARROW_DEST,
ConnectLine.LINE_TYPE_RECT_VERTICAL, Color.BLACK));
//////////
con.add( new JConnector(escpLabel ,punto5, ConnectLine.LINE_ARROW_DEST,
ConnectLine.LINE_TYPE_RECT_HORIZONTAL, Color.BLACK));
con.add( new JConnector(punto5 ,textFieldE, ConnectLine.LINE_ARROW_SOURCE,
ConnectLine.LINE_TYPE_RECT_VERTICAL, Color.BLACK));
con.add(new JConnector(punto5 ,tabbedMonitor, ConnectLine.LINE_ARROW_DEST,
ConnectLine.LINE_TYPE_RECT_VERTICAL, Color.BLACK));
////////
con.add( new JConnector(punto6 ,textFieldE, ConnectLine.LINE_ARROW_DEST,
ConnectLine.LINE_TYPE_RECT_VERTICAL, Color.BLACK));
con.add(new JConnector(punto6 ,keyboardButton, ConnectLine.LINE_ARROW_SOURCE,
ConnectLine.LINE_TYPE_RECT_VERTICAL, Color.BLACK));
/////////
con.add( new JConnector(eaLabel ,punto7, ConnectLine.LINE_ARROW_DEST,
ConnectLine.LINE_TYPE_RECT_HORIZONTAL, Color.BLACK));
con.add( new JConnector(punto7 ,aluLabel, ConnectLine.LINE_ARROW_SOURCE,
ConnectLine.LINE_TYPE_RECT_VERTICAL, Color.BLACK));
con.add(new JConnector(punto7 ,textFieldA, ConnectLine.LINE_ARROW_DEST,
ConnectLine.LINE_TYPE_RECT_VERTICAL, Color.BLACK));
con.add( new JConnector(resaLabel ,aluLabel, ConnectLine.LINE_ARROW_DEST,
ConnectLine.LINE_TYPE_RECT_HORIZONTAL, Color.BLACK));
///////
con.add( new JConnector(saLabel ,punto8, ConnectLine.LINE_ARROW_DEST,
152
ConnectLine.LINE_TYPE_RECT_HORIZONTAL, Color.BLACK));
con.add( new JConnector(punto8 ,textFieldA, ConnectLine.LINE_ARROW_SOURCE,
ConnectLine.LINE_TYPE_RECT_VERTICAL, Color.BLACK));
con.add(new JConnector(punto8 ,busLabel, ConnectLine.LINE_ARROW_DEST,
ConnectLine.LINE_TYPE_RECT_VERTICAL, Color.BLACK));
con.add( new JConnector(point ,punto8, ConnectLine.LINE_ARROW_NONE,
ConnectLine.LINE_TYPE_RECT_HORIZONTAL, Color.BLACK));
con.add( new JConnector(point ,aluLabel, ConnectLine.LINE_ARROW_DEST,
ConnectLine.LINE_TYPE_RECT_VERTICAL, Color.BLACK));
////////
con.add( new JConnector(eoLabel ,punto9, ConnectLine.LINE_ARROW_DEST,
ConnectLine.LINE_TYPE_RECT_HORIZONTAL, Color.BLACK));
con.add( new JConnector(punto9 ,busLabel, ConnectLine.LINE_ARROW_SOURCE,
ConnectLine.LINE_TYPE_RECT_VERTICAL, Color.BLACK));
con.add(new JConnector(punto9 ,aluLabel, ConnectLine.LINE_ARROW_DEST,
ConnectLine.LINE_TYPE_RECT_VERTICAL, Color.BLACK));
////////
con.add( new JConnector(sumaLabel ,aluLabel, ConnectLine.LINE_ARROW_DEST,
ConnectLine.LINE_TYPE_RECT_HORIZONTAL, Color.BLACK));
con.add( new JConnector(multaLabel ,aluLabel, ConnectLine.LINE_ARROW_DEST,
ConnectLine.LINE_TYPE_RECT_HORIZONTAL, Color.BLACK));
con.add( new JConnector(divaLabel ,aluLabel, ConnectLine.LINE_ARROW_DEST,
ConnectLine.LINE_TYPE_RECT_HORIZONTAL, Color.BLACK));
con.add( new JConnector(modaLabel ,aluLabel, ConnectLine.LINE_ARROW_DEST,
ConnectLine.LINE_TYPE_RECT_HORIZONTAL, Color.BLACK));
/////
con.add( new JConnector(incpLabel ,textFieldP, ConnectLine.LINE_ARROW_DEST,
ConnectLine.LINE_TYPE_RECT_HORIZONTAL, Color.BLACK));
////
con.add( new JConnector(epLabel ,punto10, ConnectLine.LINE_ARROW_DEST,
ConnectLine.LINE_TYPE_RECT_HORIZONTAL, Color.BLACK));
con.add( new JConnector(punto10 ,textFieldP, ConnectLine.LINE_ARROW_DEST,
ConnectLine.LINE_TYPE_RECT_VERTICAL, Color.BLACK));
con.add(new JConnector(punto10 ,sBusLabel, ConnectLine.LINE_ARROW_SOURCE,
ConnectLine.LINE_TYPE_RECT_VERTICAL, Color.BLACK));
///////
con.add( new JConnector(spLabel ,punto11, ConnectLine.LINE_ARROW_DEST,
ConnectLine.LINE_TYPE_RECT_HORIZONTAL, Color.BLACK));
con.add( new JConnector(punto11 ,textFieldP, ConnectLine.LINE_ARROW_SOURCE,
ConnectLine.LINE_TYPE_RECT_VERTICAL, Color.BLACK));
con.add(new JConnector(punto11 ,sBusLabel, ConnectLine.LINE_ARROW_DEST,
ConnectLine.LINE_TYPE_RECT_VERTICAL, Color.BLACK));
//////
con.add( new JConnector(esLabel ,punto12, ConnectLine.LINE_ARROW_DEST,
ConnectLine.LINE_TYPE_RECT_HORIZONTAL, Color.BLACK));
con.add( new JConnector(punto12 ,sBusLabel, ConnectLine.LINE_ARROW_SOURCE,
ConnectLine.LINE_TYPE_RECT_VERTICAL, Color.BLACK));
con.add(new JConnector(punto12 ,textFieldS, ConnectLine.LINE_ARROW_DEST,
ConnectLine.LINE_TYPE_RECT_VERTICAL, Color.BLACK));
//////
con.add( new JConnector(sdLabel ,punto13, ConnectLine.LINE_ARROW_DEST,
ConnectLine.LINE_TYPE_RECT_HORIZONTAL, Color.BLACK));
con.add( new JConnector(punto13 ,textFieldI, ConnectLine.LINE_ARROW_SOURCE,
ConnectLine.LINE_TYPE_RECT_VERTICAL, Color.BLACK));
con.add(new JConnector(punto13 ,sBusLabel, ConnectLine.LINE_ARROW_DEST,
ConnectLine.LINE_TYPE_RECT_VERTICAL, Color.BLACK));
//////
153
con.add( new JConnector(eiLabel ,punto14, ConnectLine.LINE_ARROW_DEST,
ConnectLine.LINE_TYPE_RECT_HORIZONTAL, Color.BLACK));
con.add( new JConnector(punto14 ,busLabel, ConnectLine.LINE_ARROW_SOURCE,
ConnectLine.LINE_TYPE_RECT_VERTICAL, Color.BLACK));
con.add(new JConnector(punto14 ,textFieldI, ConnectLine.LINE_ARROW_DEST,
ConnectLine.LINE_TYPE_RECT_VERTICAL, Color.BLACK));
//////
con.add( new JConnector(lecmLabel ,point2, ConnectLine.LINE_ARROW_DEST,
ConnectLine.LINE_TYPE_RECT_HORIZONTAL, Color.BLACK));
con.add( new JConnector(escmLabel ,point3, ConnectLine.LINE_ARROW_DEST,
ConnectLine.LINE_TYPE_RECT_HORIZONTAL, Color.BLACK));
con.add( new JConnector(textFieldT ,point5, ConnectLine.LINE_ARROW_BOTH,
ConnectLine.LINE_TYPE_RECT_HORIZONTAL, Color.BLACK));
//////
//Añadimos las flechas al panel que contiene el esquema del computador
computerGraphics.addConnectors(con);
Action actionLimpiarConsola = new AbstractAction("Limpiar", null) {
private static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent e) {
consolaPane.setText("");
}
};
//menú que sirve para limpiar la consola
JPopupMenu popup = new JPopupMenu();
popup.add(actionLimpiarConsola);
MouseListener popupListener = new PopupListener(popup);
consolaPane.addMouseListener(popupListener);
memoriaTable = new JTable();
memoriaTable.setModel(new DefaultTableModel()
{
/**
*
*/
private static final long serialVersionUID = 1L;
public boolean isCellEditable(int rowIndex, int colIndex) {
return false;
}
});
//Los usuarios solo deberían ser capaces de seleccionar una fila/instrucción
ListSelectionModel msm = memoriaTable.getSelectionModel();
msm.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
scrollAllMemory.setViewportView(memoriaTable);
//Actualiza los registros y señales del computador en la interfaz gráfica
setRegistersBase(Base.DECIMAL);
//El buffer inicial no contiene datos
inputBuffer = null;
}
@Override
public void writeNumberToScreen() {
addConsoleOutput("" + computer.getState().getE());
}
@Override
public void stateChanged() {
//Recolectamos el estado del computador
ComputerState c = computer.getState();
Color myColor = null;
if(c.getSemiState() == VirtualComputer.First_Semistep)
{
myColor = new Color(0, 184, 245);
}
else
{
myColor = new Color(245, 0, 0);
}
/////////////////////////////////////
//Actualizamos el estado de todas las señales
if(c.getSignal(ComputerSignal.ET) == true)
{
etLabel.flash(myColor);
}
else
{
154
etLabel.restart();
}
if(c.getSignal(ComputerSignal.ST) == true)
{
stLabel.flash(myColor);
}
else
{
stLabel.restart();
}
if(c.getSignal(ComputerSignal.EE) == true)
{
eeLabel.flash(myColor);
}
else
{
eeLabel.restart();
}
if(c.getSignal(ComputerSignal.SE) == true)
{
seLabel.flash(myColor);
}
else
{
seLabel.restart();
}
if(c.getSignal(ComputerSignal.ESCP) == true)
{
escpLabel.flash(myColor);
}
else
{
escpLabel.restart();
}
if(c.getSignal(ComputerSignal.LEET) == true)
{
leetLabel.flash(myColor);
}
else
{
leetLabel.restart();
}
if(c.getSignal(ComputerSignal.EA) == true)
{
eaLabel.flash(myColor);
}
else
{
eaLabel.restart();
}
if(c.getSignal(ComputerSignal.SA) == true)
{
saLabel.flash(myColor);
}
else
{
saLabel.restart();
}
if(c.getSignal(ComputerSignal.EO) == true)
{
eoLabel.flash(myColor);
}
else
{
eoLabel.restart();
}
if(c.getSignal(ComputerSignal.SUMA) == true)
{
sumaLabel.flash(myColor);
}
else
{
sumaLabel.restart();
}
if(c.getSignal(ComputerSignal.RESA) == true)
{
resaLabel.flash(myColor);
}
else
{
resaLabel.restart();
}
if(c.getSignal(ComputerSignal.MULTA) == true)
{
multaLabel.flash(myColor);
}
else
{
multaLabel.restart();
}
if(c.getSignal(ComputerSignal.DIVA) == true)
{
155
divaLabel.flash(myColor);
}
else
{
divaLabel.restart();
}
if(c.getSignal(ComputerSignal.MODA) == true)
{
modaLabel.flash(myColor);
}
else
{
modaLabel.restart();
}
if(c.getSignal(ComputerSignal.INCP) == true)
{
incpLabel.flash(myColor);
}
else
{
incpLabel.restart();
}
if(c.getSignal(ComputerSignal.EP) == true)
{
epLabel.flash(myColor);
}
else
{
epLabel.restart();
}
if(c.getSignal(ComputerSignal.SP) == true)
{
spLabel.flash(myColor);
}
else
{
spLabel.restart();
}
if(c.getSignal(ComputerSignal.ES) == true)
{
esLabel.flash(myColor);
}
else
{
esLabel.restart();
}
if(c.getSignal(ComputerSignal.SD) == true)
{
sdLabel.flash(myColor);
}
else
{
sdLabel.restart();
}
if(c.getSignal(ComputerSignal.EI) == true)
{
eiLabel.flash(myColor);
}
else
{
eiLabel.restart();
}
if(c.getSignal(ComputerSignal.ESCM) == true)
{
escmLabel.flash(myColor);
}
else
{
escmLabel.restart();
}
if(c.getSignal(ComputerSignal.LECM) == true)
{
lecmLabel.flash(myColor);
}
else
{
lecmLabel.restart();
}
if(c.hasRegisterChanged(ComputerRegister.A) == true)
{
textFieldA.flash(myColor);
}
else {
textFieldA.restart();
}
if(c.hasRegisterChanged(ComputerRegister.E) == true)
{
textFieldE.flash(myColor);
}
else {
textFieldE.restart();
}
156
if(c.hasRegisterChanged(ComputerRegister.T) == true)
{
textFieldT.flash(myColor);
}
else {
textFieldT.restart();
}
if(c.hasRegisterChanged(ComputerRegister.I) == true)
{
textFieldI.flash(myColor);
if(base == Base.BINARY)
{
textFieldCO.flash(myColor);
textFieldMD.flash(myColor);
}
else
{
textFieldCO.restart();
textFieldMD.restart();
}
}
else {
textFieldI.restart();
textFieldCO.restart();
textFieldMD.restart();
}
if(c.hasRegisterChanged(ComputerRegister.S) == true)
{
textFieldS.flash(myColor);
}
else {
textFieldS.restart();
}
if(c.hasRegisterChanged(ComputerRegister.P) == true)
{
textFieldP.flash(myColor);
}
else {
textFieldP.restart();
}
if(c.hasChangedMemory() == true)
{
pTableRenderer.flash(c.getChangedMemory());
memoriaTableRenderer.flash(c.getChangedMemory());
}
else
{
pTableRenderer.restart();
memoriaTableRenderer.restart();
}
//las señales han sido leidas
//c.resetSignalsRegisters();
/////////////////////////////////////
//Actualizamos la posición de memoria seleccionada en el visor de memoria entorno a P
selectNextInstructionInMemoryNearP(c.getP());
//Actualizamos los registros, dependiendo de la base usada
try{
if(base == Base.BINARY)
{
Instruction i = new Instruction();
i.setInstructionSigned(c.getA());
textFieldA.setText(addZeros(Integer.toString(i.getDataUnsigned(), 2),
i.setInstructionSigned(c.getP());
textFieldP.setText(addZeros(Integer.toString(i.getDataUnsigned(), 2),
i.setInstructionSigned(c.getS());
textFieldS.setText(addZeros(Integer.toString(i.getDataUnsigned(), 2),
i.setInstructionSigned(c.getI());
String s = addZeros(Integer.toString(i.getDataUnsigned(), 2), 16);
String co = s.substring(0, 4);
String md = s.substring(4, 5);
String d = s.substring(5);
textFieldCO.setText(co);
textFieldMD.setText(md);
textFieldI.setText(d);
i.setInstructionSigned(c.getT());
textFieldT.setText(addZeros(Integer.toString(i.getDataUnsigned(), 2),
i.setInstructionSigned(c.getE());
textFieldE.setText(addZeros(Integer.toString(i.getDataUnsigned(), 2),
}
else if(base == Base.DECIMAL)
{
textFieldA.setText(Integer.toString(c.getA(), 10));
textFieldP.setText(Integer.toString(c.getP(), 10));
textFieldS.setText(Integer.toString(c.getS(), 10));
textFieldI.setText(Integer.toString(c.getI(), 10));
textFieldT.setText(Integer.toString(c.getT(), 10));
textFieldE.setText(Integer.toString(c.getE(), 10));
textFieldCO.setText("");
textFieldMD.setText("");
}
else if(base == Base.HEXADECIMAL)
157
16));
11));
11));
16));
16));
{
Instruction i = new Instruction();
i.setInstructionSigned(c.getA());
textFieldA.setText(addZeros(Integer.toString(i.getDataUnsigned(),
i.setInstructionSigned(c.getP());
textFieldP.setText(addZeros(Integer.toString(i.getDataUnsigned(),
i.setInstructionSigned(c.getS());
textFieldS.setText(addZeros(Integer.toString(i.getDataUnsigned(),
i.setInstructionSigned(c.getI());
textFieldI.setText(addZeros(Integer.toString(i.getDataUnsigned(),
i.setInstructionSigned(c.getT());
textFieldT.setText(addZeros(Integer.toString(i.getDataUnsigned(),
i.setInstructionSigned(c.getE());
textFieldE.setText(addZeros(Integer.toString(i.getDataUnsigned(),
textFieldCO.setText("");
textFieldMD.setText("");
}
}
catch (Exception excep)
{
}
}
/**
* Añade ceros a la cadena 's' hasta que dicha cadena tenga una longitud 'a'
* @param s
* @param a
* @return
*/
String addZeros(String s, int a)
{
String r = "";
int b = a - s.length();
if (b > 0)
{
for(int j = 0; j < b; j++)
{
r = r + "0";
}
}
r = r + s;
return r;
}
@Override
public void memoryChanged(Instruction i) {
try {
changeMemoryAddress(i);
}
catch(Exception e)
{
// TODO Auto-generated method stub
}
}
@Override
public void writeCharacterToScreen() {
// TODO Auto-generated method stub
char c = (char)computer.getState().getE();
addConsoleOutput(Character.toString(c));
}
@Override
public void itemStateChanged(ItemEvent itemEvent) {
int state = itemEvent.getStateChange();
if (state == ItemEvent.SELECTED) {
isCheckBoxSelected = true;
System.out.println("SELECTED");
}
else if (state == ItemEvent.DESELECTED) {
isCheckBoxSelected = false;
System.out.println("DESELECTED");
}
}
}
158
16), 4));
16), 4));
16), 4));
16), 4));
16), 4));
16), 4));
11.1.11 ProjectFile.java
package xenon;
import java.io.File;
import javax.swing.tree.DefaultMutableTreeNode;
/**
*
* @brief Define un fichero que pertenece a un proyecto.
*
*/
public class ProjectFile
{
public DefaultMutableTreeNode fnode; //Nodo perteneciente al fichero en el árbol de ficheros
public enum FileType {BINARY, TEXT, CODE}; //Tipos de fichero; Código binario, código ensamblador o texto.
public FileType type; //Tipo de fichero
public File file; //Ruta del fichero en el sistema de archivos
public Project project; //Proyecto al que pertenece el fichero
/**
* @brief Devuelve el nombre del fichero en una cadena.
*/
public String toString()
{
String s = "";
if(file != null)
{
s = file.getName();
}
return s;
}
/**
* @brief Constructor.
* Las extensiones reconocidas para los ficheros de un proyecto
* son ls2 (código) y ece (binario). El resto de archivos es tratado
* como texto.
*/
public ProjectFile(File f, Project p)
{
file = f;
String arg1 = f.getName().toLowerCase();
if(arg1.lastIndexOf('.')>0)
{
// Obtener el último índice del carácter '.'
int lastIndex = arg1.lastIndexOf('.');
// Obtener extensión
String str = arg1.substring(lastIndex);
// Comprobar la extensión del fichero
if(str.equals(".ls2"))
{
type = FileType.CODE;
}
else if(str.equals(".ece"))
{
type = FileType.BINARY;
}
else
{
type = FileType.TEXT;
}
}
project = p;
}
/**
* @brief Asigna 'no' como nodo de este fichero en el árbol de proyectos.
* @param no
*/
public void setNode(DefaultMutableTreeNode no)
{
fnode = no;
}
}
159
11.1.12 TabsManager.java
package xenon;
import
import
import
import
import
java.io.BufferedWriter;
java.io.File;
java.io.FileWriter;
java.io.IOException;
java.util.ArrayList;
import
import
import
import
javax.swing.JFileChooser;
javax.swing.JOptionPane;
javax.swing.JTabbedPane;
javax.swing.JTextArea;
/**
* @brief Clase gestora de las pestañas.
*
*/
public class TabsManager{
private JTabbedPane tabbedFilePane; //Panel que contiene las pestañas
/**
* @brief Devuelve el panel de pestañas
* @return
*/
public JTabbedPane getTabbedPane()
{
return tabbedFilePane;
}
/**
* @brief Constructor
* @param tab
*/
public TabsManager(JTabbedPane tab)
{
tabbedFilePane = tab;
}
/**
* @brief Busca una pestaña que contenga el fichero pfile
* @param pfile
* @return null si ninguna pestaña contiene pfile, en caso contrario devuelve dicha pestaña
*/
public Tab searchTab(ProjectFile pfile)
{
//TODO:
Tab tt = null;
boolean bFlag = true;
for(int i = 0, n = tabbedFilePane.getTabCount(); i < n && bFlag; i++)
{
Tab t = (Tab)tabbedFilePane.getComponentAt(i);
if(t.pFile == pfile)
{
bFlag = false;
tt = t;
break;
}
}
return tt;
}
/**
* Elimina la pestaña sin preguntar si quieres guardar el fichero.
* @param t
*/
public void dontAskAndRemoveTab(Tab t)
{
tabbedFilePane.remove(t);
}
/**
* @brief Si el fichero ha sido modificado, pregunta si quieres guardarlo. Entonces lo cierra.
* @param t
*/
public void askAndRemoveTab(Tab t)
{
int i = tabbedFilePane.indexOfComponent(t);
if (i != -1) {
if(t.isModified())
{
Object[] options = {"Si",
"No",
"Cancelar"};
int n = JOptionPane.showOptionDialog(null, "'" + t.pFile.file.getName() + "'" +
" ha sido modificado. ¿Desea guardar los cambios realizados?",
"Guardar Fichero",
JOptionPane.YES_NO_CANCEL_OPTION,
160
JOptionPane.QUESTION_MESSAGE,
null,
options,
options[0]);
if(n == JOptionPane.YES_OPTION)
{
saveTabTo(t, t.pFile.file.getPath());
tabbedFilePane.remove(t);
}
else if(n == JOptionPane.NO_OPTION)
{
tabbedFilePane.remove(t);
}
else if(n == JOptionPane.CANCEL_OPTION)
{
//Do nothing!
}
}
else
{
tabbedFilePane.remove(t);
}
}
}
/**
* @brief Elimina una pestaña a partir de su etiqueta ButtonTabComponent,
* que contiene el nombre del archivo y el botón en forma de X que sirve para cerrarla.
* @param ct
*/
public void removeTab(ButtonTabComponent ct)
{
int i = tabbedFilePane.indexOfTabComponent(ct);
Tab t = (Tab)tabbedFilePane.getComponentAt(i);
askAndRemoveTab(t);
}
/**
* @brief Este método añadirá una pestaña al panel de pestañas si no existe una pestaña con el fichero
* pfile. En otro caso seleccionará y mostrará dicha pestaña.
*/
public void addTab(ProjectFile pfile)
{
//Comprobamos si existe una pestaña con ese fichero
boolean bFlag = true;
for(int i = 0, n = tabbedFilePane.getTabCount(); i < n && bFlag; i++)
{
Tab t = (Tab)tabbedFilePane.getComponentAt(i);
if(t.pFile == pfile) //La pestaña existe, la seleccionamos y mostramos
{
bFlag = false;
tabbedFilePane.setSelectedIndex(i);
}
}
if(bFlag == true) { //No existe, luego añadimos la pestaña
JTextArea textArea = new JTextArea();
Tab t = new Tab(textArea, pfile);
tabbedFilePane.addTab(null, t);
tabbedFilePane.setSelectedComponent(t);
int index = tabbedFilePane.indexOfComponent(t);
ButtonTabComponent btc = new ButtonTabComponent(this,pfile.file.getName());
t.setLabel(btc.getLabel());
tabbedFilePane.setTabComponentAt(index,btc);
}
}
/**
* @brief Guarda el fichero de una pestaña t en la ruta path.
* @param t
* @param path
*/
private void saveTabTo(Tab t, String path)
{
File fileName = new File(path);
if (fileName != null)
{
if(t.pFile.type == ProjectFile.FileType.CODE || t.pFile.type == ProjectFile.FileType.TEXT)
{
System.out.println("Guardando " + path + " ...");
try {
BufferedWriter outFile = new BufferedWriter(new FileWriter(fileName));
outFile.write(t.textArea.getText()); //put in textfile
outFile.close();
}
catch (IOException ex) {
}
} else if(t.pFile.type == ProjectFile.FileType.BINARY)
161
{
}
}
}
/**
* @brief Guarda el fichero de la pestaña actualmente seleccionado.
*/
public void saveCurrentlySelectedTab()
{
if(tabbedFilePane.getTabCount() > 0)
{
Tab t = (Tab)tabbedFilePane.getComponentAt(tabbedFilePane.getSelectedIndex());
saveTabTo(t, t.pFile.file.getPath());
t.setModified(false);
}
}
/**
* @brief Devuelve la pestaña actualmente seleccionada, o null si no existe ninguna pestaña.
* @return
*/
public Tab getCurrentlySelectedTab()
{
int i = tabbedFilePane.getSelectedIndex();
return (i >= 0)? (Tab)tabbedFilePane.getComponentAt(i): null;
}
/**
* @brief Crea un diálogo que pregunta dónde se quiere guardar el texto de la actual pestaña, y lo guarda.
*/
public void saveCurrentlySelectedTabAs()
{
if(tabbedFilePane.getTabCount() > 0)
{
Tab t = (Tab)tabbedFilePane.getComponentAt(tabbedFilePane.getSelectedIndex());
JFileChooser SaveAs = new JFileChooser();
int actionDialog = SaveAs.showDialog(null, "Guardar Como...");
if(actionDialog == JFileChooser.APPROVE_OPTION)
{
saveTabTo(t, SaveAs.getSelectedFile().getPath());
}
}
}
/**
* @brief Guarda los cambios realizados en los ficheros de todas las pestañas.
*/
public void saveAllTabs()
{
for(int i = 0, n = tabbedFilePane.getTabCount(); i < n; i++)
{
Tab t = (Tab)tabbedFilePane.getComponentAt(i);
saveTabTo(t, t.pFile.file.getPath());
t.setModified(false);
}
}
/**
* @brief Comprueba si el fichero ha sido modificado y pregunta al usuario si quiere guardar los cambios.
*/
public void saveIfModified(ProjectFile codeToDebug)
{
boolean bFlag = true;
for(int i = 0, n = tabbedFilePane.getTabCount(); i < n && bFlag; i++)
{
Tab t = (Tab)tabbedFilePane.getComponentAt(i);
if(t.pFile == codeToDebug && t.isModified())
{
bFlag = false;
Object[] options = {"Si",
"No"};
int ss = JOptionPane.showOptionDialog(null,
"El fichero " +codeToDebug.file.getName() +
" ha sido modificado. ¿Desea guardar los cambios realizados?",
"Guardar fichero",
JOptionPane.YES_NO_OPTION,
JOptionPane.QUESTION_MESSAGE,
null,
options,
options[0]);
if(ss == JOptionPane.YES_OPTION)
{
saveTabTo(t, t.pFile.file.getPath());
t.setModified(false);
}
}
}
162
}
/**
* Cierra todas las pestañas del proyecto p.
* @param p
* @return
*/
public boolean closeAllTabsOfProject(Project p)
{
if (p == null){
return false;
}
boolean result = true;
ArrayList<Tab> list = new ArrayList<Tab>();
boolean modified = false;
for(int i = 0, n = tabbedFilePane.getTabCount(); i < n ; i++)
{
Tab t = (Tab)tabbedFilePane.getComponentAt(i);
//System.out.println(t);
if(t.pFile.project == p)
{
list.add(t);
if(t.isModified())
{
modified = true;
}
}
}
if(modified)
{
Object[] options = {"Si",
"No",
"Cancelar"};
int n = JOptionPane.showOptionDialog(null,
"Algunos ficheros han sido modificados. ¿Desea guardar los cambios realizados?",
"Guardar Ficheros",
JOptionPane.YES_NO_CANCEL_OPTION,
JOptionPane.QUESTION_MESSAGE,
null,
options,
options[0]);
if(n == JOptionPane.YES_OPTION)
{
for(Tab t: list)
{
if (t.isModified())
{
saveTabTo(t, t.pFile.file.getPath());
}
tabbedFilePane.remove(t);
}
}
else if(n == JOptionPane.NO_OPTION)
{
for(Tab t: list)
{
tabbedFilePane.remove(t);
}
}
else if(n == JOptionPane.CANCEL_OPTION)
{
result = false;
}
}
else
{
for(Tab t: list)
{
tabbedFilePane.remove(t);
}
}
return result;
}
/**
* @brief Cierra la pestaña actualmente seleccionada.
*/
public void closeCurrentlySelectedTab()
{
if(tabbedFilePane.getTabCount() > 0)
{
Tab t = (Tab)tabbedFilePane.getComponentAt(tabbedFilePane.getSelectedIndex());
askAndRemoveTab(t);
}
}
/**
* @brief Cierra todas las pestañas, preguntando si guardar cambios en aquellos ficheros que se han modificado.
*/
163
public void closeAllTabs()
{
ArrayList<Tab> list = new ArrayList<Tab>();
boolean modified = false;
for(int i = 0, m = tabbedFilePane.getTabCount(); i < m ; i++)
{
Tab t = (Tab)tabbedFilePane.getComponentAt(i);
list.add(t);
//System.out.println(t);
if(t.isModified())
{
modified = true;
}
}
if(modified)
{
Object[] options = {"Si",
"No",
"Cancelar"};
int dialogResult = JOptionPane.showOptionDialog(null,
"Algunos ficheros han sido modificados. ¿Desea guardar los cambios realizados?",
"Guardar Ficheros",
JOptionPane.YES_NO_CANCEL_OPTION,
JOptionPane.QUESTION_MESSAGE,
null,
options,
options[0]);
if(dialogResult == JOptionPane.YES_OPTION)
{
for(Tab t: list)
{
if (t.isModified())
{
saveTabTo(t, t.pFile.file.getPath());
}
tabbedFilePane.remove(t);
}
}
else if(dialogResult == JOptionPane.NO_OPTION)
{
for(Tab t: list)
{
tabbedFilePane.remove(t);
}
}
else if(dialogResult == JOptionPane.CANCEL_OPTION)
{
//Do nothing!
}
}
else
{
for(Tab t: list)
{
tabbedFilePane.remove(t);
}
}
} }
164
11.1.13 Project.java
package xenon;
import java.io.File;
import java.util.ArrayList;
import javax.swing.tree.DefaultMutableTreeNode;
/**
*
* @brief Define un proyecto y sus propiedades básicas
*
*/
public class Project
{
public File file; //Localización del proyecto
public ArrayList <ProjectFile> projectFiles; //Ficheros pertenecientes al proyecto
DefaultMutableTreeNode pnode; //Nodo del proyecto en el árbol de proyectos
public Project()
{
file = null;
projectFiles = new ArrayList <ProjectFile>();
}
public String toString()
{
String s = "";
if(file != null)
{
s = file.getName();
}
return s;
}
};
165
11.1.14 VirtualComputer.java
package xenon;
import java.util.ArrayList;
import java.util.EnumMap;
/**
* @brief Clase que abstrae el comportamiento del computador.
*
*/
public class VirtualComputer {
public final static int First_Semistep = 0;
public final static int Last_Semistep = 1;
private Instruction[] memoryMap; //Mapa de memoria del computador
private
private
private
private
Instruction[] InitialMemoryMap; //Mapa de memoria inicial del computador
ComputerState state;
//Estado del computador
boolean trafficLight;
//Semáforo que asegura una ejecución ordenada.
int semiStep;
/**
* @brief Listener del computador
*
*/
interface VirtualComputerListener
{
/**
* Este método será llamado cuandoquiera que el computador quiera escribir números en pantalla.
*/
public void writeNumberToScreen();
/**
* Este método será llamado cuandoquiera que el estado del computador cambie.
*/
public void stateChanged();
/**
* Este método será llamado cuando el contenido de la dirección de memoria i cambie.
*/
public void memoryChanged(Instruction i);
/**
* Este método será llamado cuandoquiera que el computador quiera escribir un carácter en pantalla.
*/
public void writeCharacterToScreen();
}
/**
* @brief Enumeración de las señales del computador.
*/
public enum ComputerSignal{
ET, ST, EE, SE, ESCP, LEET, EA, SA, EO, SUMA, RESA, MULTA, DIVA, MODA, INCP, EP, SP, ES, SD, EI, LECM, ESCM;
}
/**
* @brief Enumeración de los registros del computador.
*
*/
public enum ComputerRegister{
A, S, T, P, I, E;
}
/**
* @brief Clase que define el estado del computador, a nivel de registros y señales del mismo.
*
*/
class ComputerState
{
//A, I, T, E: signed 16 bit, [-32768, 32767]
//P, S: unsigned 11 bit, [0, 2047]
VirtualComputerListener listener;
private EnumMap<ComputerSignal, Boolean> signals;
//Mapa de las señales
private EnumMap<ComputerRegister, Boolean> changedRegisters; //Mapa de los registros
private boolean changedMemory;
private int dirOfChanchedMemory;
private int semiStep;
private int A, S, T, P, I, E;
/**
* @brief Constructor que inicializa los parámetros del objeto.
*/
ComputerState()
{
semiStep = First_Semistep;
changedMemory = false;
dirOfChanchedMemory = -1;
listener = null;
A = S = T = P = I = E = 0;
signals = new EnumMap<ComputerSignal, Boolean>(ComputerSignal.class);
changedRegisters = new EnumMap<ComputerRegister, Boolean>(ComputerRegister.class);
ComputerSignal[] c = ComputerSignal.values();
for(ComputerSignal i: c)
166
{
signals.put(i, false);
}
ComputerRegister[] r = ComputerRegister.values();
for(ComputerRegister i: r)
{
changedRegisters.put(i, false);
}
}
/**
* @brief Método que marca si una posición de memoria ha sido modificada en la ejecución de la última instrucción.
* @param d Posición de memoria que ha cambiado. Ha de pertenecer al rango de memoria o de lo
* contrario indicará que ninguna posición de memoria ha sido modificada en la ejecución
* de la última instrucción.
*/
void setChangedMemory(int d)
{
if (d > 0 && d < Instruction.Memory_Address_Limit)
{
changedMemory = true;
dirOfChanchedMemory = d;
}
else
{
changedMemory = false;
dirOfChanchedMemory = -1;
}
}
/**
* @brief Indica si la última instrucción ejecutada ha modificado una posición de memoria.
* @return
*/
boolean hasChangedMemory()
{
return changedMemory;
}
void setSemiState(int s)
{
semiStep = s;
}
int getSemiState()
{
return semiStep;
}
/**
* @detail Indica qué posición de memoria ha sido modificada tras la última instrucción ejecutada.
* En caso de que no se haya modificado ninguna posición, devolverá -1.
* @return
*/
int getChangedMemory()
{
return dirOfChanchedMemory;
}
/**
* @brief Llama al listener para indicarle el estado actual del computador.
*/
public void sendSignals()
{
callChange();
}
/**
* @brief Devuelve al estado inicial (= no modificado) los registros del computador.
*/
public void resetSignalsRegisters()
{
changedMemory = false;
dirOfChanchedMemory = -1;
ComputerSignal[] c = ComputerSignal.values();
for(ComputerSignal i: c)
{
signals.put(i, false);
}
ComputerRegister[] r = ComputerRegister.values();
for(ComputerRegister i: r)
{
changedRegisters.put(i, false);
}
}
/**
* @brief Marca cierto registro como modificado o no modificado.
* @param s Registro
* @param b true si el registro ha sido modificado, false en caso contrario
*/
public void setRegisterChanged(ComputerRegister s, boolean b)
{
changedRegisters.put(s, b);
}
/**
* @brief Indica si cierto registro ha sido modificado por la última instrucción ejecutada.
167
* @param s Registro
* @return
*/
public boolean hasRegisterChanged(ComputerRegister s)
{
boolean b = false;
try{
b = changedRegisters.get(s);
}
catch (NullPointerException e)
{
}
return b;
}
/**
* @brief Marca cierta señal como modificada o no modificada.
* @param s señal
* @param b true si la señal ha sido modificada, false en caso contrario
*/
public void setSignal(ComputerSignal s, boolean b)
{
signals.put(s, b);
}
/**
* @brief Indica si cierta señal ha sido modificada por la última instrucción ejecutada.
* @param s Señal
* @return
*/
public boolean getSignal(ComputerSignal s)
{
boolean b = false;
try{
b = signals.get(s);
}
catch (NullPointerException e)
{
}
return b;
}
/**
* @brief Llama al listener para indicarle el estado actual del computador.
*/
private void callChange()
{
if(listener != null)
{
listener.stateChanged();
}
else
{
//throw new NullPointerException("");
}
}
/**
* Asigna un listener al ComputerState
* @param l Listener
*/
void setListener(VirtualComputerListener l)
{
listener = l;
}
/**
* Devuelve el listener.
* @return Listener
*/
VirtualComputerListener getListener()
{
return listener;
}
/**
* @brief Devuelve el contenido del registro A.
* @return Registro A.
*/
public int getA() {
return A;
}
/**
* Cambia el registro A con el dato 'a'
* @param a
* @throws Exception Registro A fuera de rango
*/
public void setA(int a) throws Exception {
if(a >= Instruction.Register_Min_Limit && a <= Instruction.Register_Max_Limit)
{
A = a;
}
else
{
throw new Exception("Registro A fuera de rango");
}
168
}
/**
* @brief Devuelve el contenido del registro S.
* @return Registro S.
*/
public int getS() {
return S;
}
/**
* Cambia el registro S con el dato 's'
* @param s
* @throws Exception Registro S fuera de rango
*/
public void setS(int s) throws Exception {
if(s >= 0 && s <= Instruction.Memory_Address_Limit)
{
S = s;
}
else
{
throw new Exception("Input register S out of boundaries");
}
}
/**
* @brief Devuelve el contenido del registro T.
* @return Registro T.
*/
public int getT() {
return T;
}
/**
* Cambia el registro T con el dato 't'
* @param t
* @throws Exception Registro T fuera de rango
*/
public void setT(int t) throws Exception {
if(t >= Instruction.Register_Min_Limit && t <= Instruction.Register_Max_Limit)
{
T = t;
}
else
{
throw new Exception("Input register T out of boundaries");
}
}
/**
* @brief Devuelve el contenido del registro P.
* @return Registro P.
*/
public int getP() {
return P;
}
/**
* Cambia el registro P con el dato 'p'
* @param p
* @throws Exception Registro P fuera de rango
*/
public void setP(int p) throws Exception {
if(p >= 0 && p <= Instruction.Memory_Address_Limit)
{
P = p;
}
else
{
throw new Exception("Input register P out of boundaries");
}
callChange();
}
/**
* @brief Devuelve el contenido del registro I.
* @return Registro I.
*/
public int getI() {
return I;
}
/**
* Cambia el registro I con el dato 'i'
* @param i
* @throws Exception Registro I fuera de rango
*/
public void setI(int i) throws Exception {
if(i >= Instruction.Register_Min_Limit && i <= Instruction.Register_Max_Limit)
{
I = i;
}
else
{
throw new Exception("Input register I out of boundaries");
}
}
169
/**
* @brief Devuelve el contenido del registro E.
* @return Registro E.
*/
public int getE() {
return E;
}
/**
* Cambia el registro E con el dato 'e'
* @param e
* @throws Exception Registro E fuera de rango
*/
public void setE(int e) throws Exception{
if(e >= Instruction.Register_Min_Limit && e <= Instruction.Register_Max_Limit)
{
E = e;
}
else
{
throw new Exception("Input register E out of boundaries");
}
}
/**
* @brief Incrementa en una unidad el registro P.
*/
public void incrementP()
{
if(P >= Instruction.Memory_Address_Limit)
{
P = 0;
}
else
{
P += 1;
}
}
}
/**
* @brief Constructor del computador, inicializa variables.
*/
VirtualComputer()
{
semiStep = First_Semistep;
trafficLight = false;
memoryMap = new Instruction[Instruction.Memory_Address_Limit+1];
InitialMemoryMap = new Instruction[Instruction.Memory_Address_Limit+1];
for(int i = 0; i < memoryMap.length; i++)
{
memoryMap[i] = new Instruction();
InitialMemoryMap[i] = new Instruction();
}
setMemoryMapToZero();
state = new ComputerState();
}
/**
* @brief Constructor del computador que inicializa su memoria con 'memory'
* @param memory Mapa de memoria del computador
*/
VirtualComputer(ArrayList<Instruction> memory)
{
memoryMap = new Instruction[Instruction.Memory_Address_Limit+1];
InitialMemoryMap = new Instruction[Instruction.Memory_Address_Limit+1];
for(int i = 0; i < memoryMap.length; i++)
{
memoryMap[i] = new Instruction();
InitialMemoryMap[i] = new Instruction();
}
setMemoryMap(memory);
state = new ComputerState();
/*
//Innecesario, ya lo hace setMemoryMap(memory);
for(int i = 0; i < memoryMap.length; i++)
{
try{
InitialMemoryMap[i].setInstructionSigned(memoryMap[i].getDataSigned());
}
catch(Exception e)
{
}
}*/
}
/**
* @brief Lleva el ordenador al estado inicial.
* Pone a cero los registros y las señales, y devuelve la memoria principal a su estado inicial.
*/
public void restart()
{
try
{
state.resetSignalsRegisters();
170
state.setA(0);
state.setS(0);
state.setT(0);
state.setP(0);
state.setI(0);
state.setE(0);
for(int i = 0; i < memoryMap.length; i++)
{
if(memoryMap[i].getDataSigned() != InitialMemoryMap[i].getDataSigned())
{
memoryMap[i].setInstructionSigned(InitialMemoryMap[i].getDataSigned());
state.getListener().memoryChanged(memoryMap[i]);
}
}
}
catch(Exception e)
{
}
}
/**
* @brief Asigna un nuevo listener al computador
* @param l Listener
*/
public void setListener(VirtualComputerListener l)
{
state.setListener(l);
}
/**
* Devuelve el listener del computador
* @return Listener
*/
VirtualComputerListener getListener()
{
return state.getListener();
}
/**
* @biref Modifica la memoria del computador con 'memory'
* @param memory Mapa de memoria
*/
public void setMemoryMap(ArrayList<Instruction> memory)
{
setMemoryMapToZero();
for(Instruction i: memory)
{
memoryMap[i.getAddressLocation()]= i;
}
for(int i = 0; i < memoryMap.length; i++)
{
try{
InitialMemoryMap[i].setInstructionSigned(memoryMap[i].getDataSigned());
}
catch(Exception e)
{
}
}
}
/**
* @brief Inicializa a cero la memoria del computador.
*/
private void setMemoryMapToZero()
{
int d = 0;
for(int i = 0; i < memoryMap.length; i++)
{
try{
memoryMap[i].setInstructionSigned(d);
memoryMap[i].setAddressLocation(i);
} catch(Exception e)
{
//TODO:
}
}
}
/**
* @brief Devuelve el mapa de memoria del computador.
* @return Mapa de memoria
*/
public ArrayList<Instruction> getMemoryMap()
{
ArrayList<Instruction> a = new ArrayList<Instruction>();
for(Instruction i: memoryMap)
{
a.add(i);
}
return a;
}
/**
* Devuelve el estado del computador.
* @return
*/
171
ComputerState getState()
{
return state;
}
/**
* Devuelve M(D), la dirección de memoria contenida en la posición D
* @param d Posición de memoria
* @return
* @throws IndexOutOfBoundsException
*/
private int getIndirectAddress(int d) throws IndexOutOfBoundsException
{
int r = 0;
if(d < 0 || d > Instruction.Memory_Address_Limit)
{
throw new IndexOutOfBoundsException("" + d);
}
r = memoryMap[d].getDataSigned();
if(r < 0 || r > Instruction.Memory_Address_Limit)
{
throw new IndexOutOfBoundsException("" + r);
}
return r;
}
/**
* @brief Devuelve la próxima instrucción a ejecutar, posición que marca el registro P.
* @return
*/
public Instruction getNextInstruction()
{
return memoryMap[state.getP()];
}
public int getSemistepInfo()
{
return semiStep;
}
public ComputerState executeSemistep() throws Exception
{
//Usamos el semáforo trafficLight para que no se puedan realizar
//llamadas en paralelo/concurrentes a esta instrucción.
if(trafficLight == false)
{
trafficLight = true;
//Recogemos la instrucción a ejecutar
Instruction ins = memoryMap[state.getP()];
//Marcamos todos los registros y señales como no modificados
state.resetSignalsRegisters();
state.setSemiState(semiStep);
if(semiStep == First_Semistep)
{
try{
//int operator = ins.getInstructionOperator();
state.setS(state.getP());
state.setT(ins.getDataSigned());
state.setI(ins.getDataSigned());
//Ahora señalamos qué registros han cambiado
state.setRegisterChanged(ComputerRegister.T, true);
state.setRegisterChanged(ComputerRegister.I, true);
state.setRegisterChanged(ComputerRegister.S, true);
//Aquí mostramos las señales usadas en el transcurso de la ejecución de la instrucción.
//Algunos setSignal los comento, pero solo para no repetir llamadas iguales
//M(P) -> I equivalente a: P -> S. M(S) -> T. T -> I.
state.setSignal(ComputerSignal.SP, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);
state.sendSignals();
}
catch(IndexOutOfBoundsException exception)
{
throw new Exception("Primer semipaso de instrucción");
}
semiStep = Last_Semistep;
}
else if(semiStep == Last_Semistep)
{
if(ins.isInstruction() == true)
{
switch(ins.getOperationCode()) //Elegimos qué operación ejecutar según el código de
operación.
{
case ALT:
break;
172
case ALM:
try{
int operator = ins.getInstructionOperator();
memoryMap[operator].setInstructionSigned(state.getA());
state.getListener().memoryChanged(memoryMap[operator]);
state.setChangedMemory(memoryMap[operator].getAddressLocation());
state.setT(state.getA());
//state.setI(ins.getDataSigned());
state.setS(operator);
state.incrementP();
//Ahora señalamos qué registros han cambiado
state.setRegisterChanged(ComputerRegister.T, true);
//state.setRegisterChanged(ComputerRegister.I, true);
state.setRegisterChanged(ComputerRegister.S, true);
state.setRegisterChanged(ComputerRegister.P, true);
//Aquí mostramos las señales usadas en el transcurso de la ejecución
de la instrucción.
//Algunos setSignal los comento, pero solo para no repetir llamadas
iguales
//M(P) -> I equivalente a: P -> S. M(S) -> T. T -> I.
/*state.setSignal(ComputerSignal.SP, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);*/
//A -> M(D)
state.setSignal(ComputerSignal.SD, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.SA, true);
state.setSignal(ComputerSignal.ET, true);
state.setSignal(ComputerSignal.ESCM, true);
//P -> P+1
state.setSignal(ComputerSignal.INCP, true);
state.sendSignals();
}
catch(IndexOutOfBoundsException exception)
{
throw new Exception("ALM");
}
break;
case ALMI:
try{
int operator = getIndirectAddress( ins.getInstructionOperator() );
memoryMap[operator].setInstructionSigned(state.getA());
state.setChangedMemory(memoryMap[operator].getAddressLocation());
state.getListener().memoryChanged(memoryMap[operator]);
state.setT(state.getA());
state.setI(operator);
state.setS(operator);
state.incrementP();
//Ahora señalamos qué registros han cambiado
state.setRegisterChanged(ComputerRegister.T, true);
state.setRegisterChanged(ComputerRegister.I, true);
state.setRegisterChanged(ComputerRegister.S, true);
state.setRegisterChanged(ComputerRegister.P, true);
//Aquí mostramos las señales usadas en el transcurso de la ejecución
de la instrucción.
//Algunos setSignal los comento, pero solo para no repetir llamadas
iguales
//M(P) -> I
/*state.setSignal(ComputerSignal.SP, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);*/
//A -> M(M(D))
state.setSignal(ComputerSignal.SD, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);
//state.setSignal(ComputerSignal.SD, true);
//state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.SA, true);
state.setSignal(ComputerSignal.ET, true);
state.setSignal(ComputerSignal.ESCM, true);
//P -> P+1
state.setSignal(ComputerSignal.INCP, true);
state.sendSignals();
173
case CAR:
}
catch(IndexOutOfBoundsException exception)
{
throw new Exception("ALMI");
}
break;
try{
state.setA(memoryMap[ins.getInstructionOperator()].getDataSigned());
state.setT(state.getA());
//state.setI(ins.getDataSigned());
state.setS(ins.getInstructionOperator());
state.incrementP();
//Ahora señalamos qué registros han cambiado
state.setRegisterChanged(ComputerRegister.A, true);
state.setRegisterChanged(ComputerRegister.T, true);
//state.setRegisterChanged(ComputerRegister.I, true);
state.setRegisterChanged(ComputerRegister.S, true);
state.setRegisterChanged(ComputerRegister.P, true);
//Aquí mostramos las señales usadas en el transcurso de la ejecución
de la instrucción.
//Algunos setSignal los comento, pero solo para no repetir llamadas
iguales
//M(P) -> I
/*state.setSignal(ComputerSignal.SP, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);*/
//M(D) ->A
state.setSignal(ComputerSignal.SD, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EO, true);
state.setSignal(ComputerSignal.EA, true);
//P -> P+1
state.setSignal(ComputerSignal.INCP, true);
state.sendSignals();
}
catch(IndexOutOfBoundsException exception)
{
throw new Exception("CAR");
}
break;
case CARI:
try{
state.setA(memoryMap[ getIndirectAddress( ins.getInstructionOperator() ) ].getDataSigned());
state.setT(state.getA());
state.setI(getIndirectAddress( ins.getInstructionOperator() ));
state.setS(getIndirectAddress( ins.getInstructionOperator() ));
state.incrementP();
//Ahora señalamos qué registros han cambiado
state.setRegisterChanged(ComputerRegister.A, true);
state.setRegisterChanged(ComputerRegister.T, true);
state.setRegisterChanged(ComputerRegister.I, true);
state.setRegisterChanged(ComputerRegister.S, true);
state.setRegisterChanged(ComputerRegister.P, true);
//Aquí mostramos las señales usadas en el transcurso de la ejecución
de la instrucción.
//Algunos setSignal los comento, pero solo para no repetir llamadas
iguales
//M(P) -> I
/*state.setSignal(ComputerSignal.SP, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);*/
//M(M(D)) ->A
state.setSignal(ComputerSignal.SD, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);
//state.setSignal(ComputerSignal.SD, true);
//state.setSignal(ComputerSignal.ES, true);
//state.setSignal(ComputerSignal.LECM, true);
//state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EO, true);
state.setSignal(ComputerSignal.EA, true);
174
//P -> P+1
state.setSignal(ComputerSignal.INCP, true);
state.sendSignals();
case ESC:
}
catch(IndexOutOfBoundsException exception)
{
throw new Exception("CARI");
}
break;
try{
state.setE(memoryMap[ins.getInstructionOperator()].getDataSigned());
state.setT(state.getE());
//state.setI(ins.getDataSigned());
state.setS(ins.getInstructionOperator());
state.getListener().writeNumberToScreen();
state.incrementP();
//Ahora señalamos qué registros han cambiado
state.setRegisterChanged(ComputerRegister.E, true);
state.setRegisterChanged(ComputerRegister.T, true);
//state.setRegisterChanged(ComputerRegister.I, true);
state.setRegisterChanged(ComputerRegister.S, true);
state.setRegisterChanged(ComputerRegister.P, true);
//Aquí mostramos las señales usadas en el transcurso de la ejecución
de la instrucción.
//Algunos setSignal los comento, pero solo para no repetir llamadas
iguales
//M(P) -> I
/*state.setSignal(ComputerSignal.SP, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);*/
//M(D) ->E
state.setSignal(ComputerSignal.SD, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EE, true);
state.setSignal(ComputerSignal.ESCP, true);
//P -> P+1
state.setSignal(ComputerSignal.INCP, true);
state.sendSignals();
}
catch(IndexOutOfBoundsException exception)
{
throw new Exception("ESC");
}
break;
case ESCI:
try{
state.setE(memoryMap[ getIndirectAddress( ins.getInstructionOperator() ) ].getDataSigned());
state.setT(state.getE());
state.setI(getIndirectAddress( ins.getInstructionOperator() ));
state.setS(getIndirectAddress( ins.getInstructionOperator() ));
state.getListener().writeNumberToScreen();
state.incrementP();
//Ahora señalamos qué registros han cambiado
state.setRegisterChanged(ComputerRegister.E, true);
state.setRegisterChanged(ComputerRegister.T, true);
state.setRegisterChanged(ComputerRegister.I, true);
state.setRegisterChanged(ComputerRegister.S, true);
state.setRegisterChanged(ComputerRegister.P, true);
//Aquí mostramos las señales usadas en el transcurso de la ejecución
de la instrucción.
//Algunos setSignal los comento, pero solo para no repetir llamadas
iguales
//M(P) -> I
/*state.setSignal(ComputerSignal.SP, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);*/
//M(M(D)) ->A
state.setSignal(ComputerSignal.SD, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);
//state.setSignal(ComputerSignal.SD, true);
//state.setSignal(ComputerSignal.ES, true);
//state.setSignal(ComputerSignal.LECM, true);
//state.setSignal(ComputerSignal.ST, true);
175
state.setSignal(ComputerSignal.EE, true);
state.setSignal(ComputerSignal.ESCP, true);
//P -> P+1
state.setSignal(ComputerSignal.INCP, true);
state.sendSignals();
case LEE:
}
catch(IndexOutOfBoundsException exception)
{
throw new Exception("ESCI");
}
break;
try{
/**
* Before executing this instruction,
* the input from the keyboard should have been saved into register
E.
*/
int operator = ins.getInstructionOperator();
memoryMap[operator].setInstructionSigned(state.getE());
state.setT(state.getE());
//state.setI(ins.getDataSigned());
state.setS(operator);
state.getListener().memoryChanged(memoryMap[operator]);
state.setChangedMemory(memoryMap[operator].getAddressLocation());
state.incrementP();
//Ahora señalamos qué registros han cambiado
state.setRegisterChanged(ComputerRegister.T, true);
//state.setRegisterChanged(ComputerRegister.I, true);
state.setRegisterChanged(ComputerRegister.S, true);
state.setRegisterChanged(ComputerRegister.P, true);
//Aquí mostramos las señales usadas en el transcurso de la ejecución
de la instrucción.
//Algunos setSignal los comento, pero solo para no repetir llamadas
iguales
//M(P) -> I
/*state.setSignal(ComputerSignal.SP, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);*/
//E -> M(D)
state.setSignal(ComputerSignal.SD, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LEET, true);
state.setSignal(ComputerSignal.SE, true);
state.setSignal(ComputerSignal.ET, true);
state.setSignal(ComputerSignal.ESCM, true);
//P -> P+1
state.setSignal(ComputerSignal.INCP, true);
state.sendSignals();
}
catch(IndexOutOfBoundsException exception)
{
throw new Exception("LEE");
}
break;
case LEEI:
try{
/**
* Before executing this instruction,
* the input from the keyboard should have been saved into register
E.
*/
int operator = getIndirectAddress( ins.getInstructionOperator() );
memoryMap[operator].setInstructionSigned(state.getE());
state.setT(state.getE());
state.setI(operator);
state.setS(operator);
state.getListener().memoryChanged(memoryMap[operator]);
state.setChangedMemory(memoryMap[operator].getAddressLocation());
state.incrementP();
//Ahora señalamos qué registros han cambiado
state.setRegisterChanged(ComputerRegister.T, true);
state.setRegisterChanged(ComputerRegister.I, true);
state.setRegisterChanged(ComputerRegister.S, true);
state.setRegisterChanged(ComputerRegister.P, true);
//Aquí mostramos las señales usadas en el transcurso de la ejecución
de la instrucción.
//Algunos setSignal los comento, pero solo para no repetir llamadas
iguales
176
//M(P) -> I
/*state.setSignal(ComputerSignal.SP, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);*/
//A -> M(M(D))
state.setSignal(ComputerSignal.SD, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);
//state.setSignal(ComputerSignal.SD, true);
//state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LEET, true);
state.setSignal(ComputerSignal.SE, true);
state.setSignal(ComputerSignal.ET, true);
state.setSignal(ComputerSignal.ESCM, true);
//P -> P+1
state.setSignal(ComputerSignal.INCP, true);
state.sendSignals();
case SUM:
}
catch(IndexOutOfBoundsException exception)
{
throw new Exception("LEEI");
}
break;
try{
state.setA(state.getA() +
memoryMap[ins.getInstructionOperator()].getDataSigned());
state.setT(memoryMap[ins.getInstructionOperator()].getDataSigned());
//state.setI(ins.getDataSigned());
state.setS(ins.getInstructionOperator());
state.incrementP();
//Ahora señalamos qué registros han cambiado
state.setRegisterChanged(ComputerRegister.A, true);
state.setRegisterChanged(ComputerRegister.T, true);
//state.setRegisterChanged(ComputerRegister.I, true);
state.setRegisterChanged(ComputerRegister.S, true);
state.setRegisterChanged(ComputerRegister.P, true);
//Aquí mostramos las señales usadas en el transcurso de la ejecución
de la instrucción.
//Algunos setSignal los comento, pero solo para no repetir llamadas
iguales
//M(P) -> I
/*state.setSignal(ComputerSignal.SP, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);*/
//A+M(D) ->A
state.setSignal(ComputerSignal.SD, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EO, true);
state.setSignal(ComputerSignal.SUMA, true);
state.setSignal(ComputerSignal.EA, true);
//P -> P+1
state.setSignal(ComputerSignal.INCP, true);
state.sendSignals();
}
catch(IndexOutOfBoundsException exception)
{
throw new Exception("SUM");
}
break;
case SUMI:
try{
state.setA(state.getA() +
memoryMap[ getIndirectAddress( ins.getInstructionOperator() ) ].getDataSigned());
state.setT(memoryMap[ getIndirectAddress( ins.getInstructionOperator() ) ].getDataSigned());
state.setI(getIndirectAddress( ins.getInstructionOperator() ));
state.setS(getIndirectAddress( ins.getInstructionOperator() ));
state.incrementP();
//Ahora señalamos qué registros han cambiado
state.setRegisterChanged(ComputerRegister.A, true);
state.setRegisterChanged(ComputerRegister.T, true);
state.setRegisterChanged(ComputerRegister.I, true);
177
state.setRegisterChanged(ComputerRegister.S, true);
state.setRegisterChanged(ComputerRegister.P, true);
//Aquí mostramos las señales usadas en el transcurso de la ejecución
de la instrucción.
//Algunos setSignal los comento, pero solo para no repetir llamadas
iguales
//M(P) -> I
/*state.setSignal(ComputerSignal.SP, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);*/
//M(M(D)) ->A
state.setSignal(ComputerSignal.SD, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);
//state.setSignal(ComputerSignal.SD, true);
//state.setSignal(ComputerSignal.ES, true);
//state.setSignal(ComputerSignal.LECM, true);
//state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EO, true);
state.setSignal(ComputerSignal.SUMA, true);
state.setSignal(ComputerSignal.EA, true);
//P -> P+1
state.setSignal(ComputerSignal.INCP, true);
state.sendSignals();
case RES:
}
catch(IndexOutOfBoundsException exception)
{
throw new Exception("SUMI");
}
break;
try{
state.setA(state.getA() -
memoryMap[ins.getInstructionOperator()].getDataSigned());
state.setT(memoryMap[ins.getInstructionOperator()].getDataSigned());
//state.setI(ins.getDataSigned());
state.setS(ins.getInstructionOperator());
state.incrementP();
//Ahora señalamos qué registros han cambiado
state.setRegisterChanged(ComputerRegister.A, true);
state.setRegisterChanged(ComputerRegister.T, true);
//state.setRegisterChanged(ComputerRegister.I, true);
state.setRegisterChanged(ComputerRegister.S, true);
state.setRegisterChanged(ComputerRegister.P, true);
//Aquí mostramos las señales usadas en el transcurso de la ejecución
de la instrucción.
//Algunos setSignal los comento, pero solo para no repetir llamadas
iguales
//M(P) -> I
/*state.setSignal(ComputerSignal.SP, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);*/
//A+M(D) ->A
state.setSignal(ComputerSignal.SD, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EO, true);
state.setSignal(ComputerSignal.RESA, true);
state.setSignal(ComputerSignal.EA, true);
//P -> P+1
state.setSignal(ComputerSignal.INCP, true);
state.sendSignals();
}
catch(IndexOutOfBoundsException exception)
{
throw new Exception("RES");
}
break;
case RESI:
try{
state.setA(state.getA() memoryMap[ getIndirectAddress( ins.getInstructionOperator() ) ].getDataSigned());
state.setT(memoryMap[ getIndirectAddress( ins.getInstructionOperator() ) ].getDataSigned());
state.setI(getIndirectAddress( ins.getInstructionOperator() ));
178
state.setS(getIndirectAddress( ins.getInstructionOperator() ));
state.incrementP();
//Ahora señalamos qué registros han cambiado
state.setRegisterChanged(ComputerRegister.A, true);
state.setRegisterChanged(ComputerRegister.T, true);
state.setRegisterChanged(ComputerRegister.I, true);
state.setRegisterChanged(ComputerRegister.S, true);
state.setRegisterChanged(ComputerRegister.P, true);
//Aquí mostramos las señales usadas en el transcurso de la ejecución
de la instrucción.
//Algunos setSignal los comento, pero solo para no repetir llamadas
iguales
//M(P) -> I
/*state.setSignal(ComputerSignal.SP, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);*/
//M(M(D)) ->A
state.setSignal(ComputerSignal.SD, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);
//state.setSignal(ComputerSignal.SD, true);
//state.setSignal(ComputerSignal.ES, true);
//state.setSignal(ComputerSignal.LECM, true);
//state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EO, true);
state.setSignal(ComputerSignal.RESA, true);
state.setSignal(ComputerSignal.EA, true);
//P -> P+1
state.setSignal(ComputerSignal.INCP, true);
state.sendSignals();
case MUL:
}
catch(IndexOutOfBoundsException exception)
{
throw new Exception("RESI");
}
break;
try{
state.setA(state.getA() *
memoryMap[ins.getInstructionOperator()].getDataSigned());
state.setT(memoryMap[ins.getInstructionOperator()].getDataSigned());
//state.setI(ins.getDataSigned());
state.setS(ins.getInstructionOperator());
state.incrementP();
//Ahora señalamos qué registros han cambiado
state.setRegisterChanged(ComputerRegister.A, true);
state.setRegisterChanged(ComputerRegister.T, true);
//state.setRegisterChanged(ComputerRegister.I, true);
state.setRegisterChanged(ComputerRegister.S, true);
state.setRegisterChanged(ComputerRegister.P, true);
//Aquí mostramos las señales usadas en el transcurso de la ejecución
de la instrucción.
//Algunos setSignal los comento, pero solo para no repetir llamadas
iguales
//M(P) -> I
/*state.setSignal(ComputerSignal.SP, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);*/
//A+M(D) ->A
state.setSignal(ComputerSignal.SD, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EO, true);
state.setSignal(ComputerSignal.MULTA, true);
state.setSignal(ComputerSignal.EA, true);
//P -> P+1
state.setSignal(ComputerSignal.INCP, true);
state.sendSignals();
}
catch(IndexOutOfBoundsException exception)
{
throw new Exception("MUL");
}
break;
case MULI:
179
try{
state.setA(state.getA() *
memoryMap[ getIndirectAddress( ins.getInstructionOperator() ) ].getDataSigned());
state.setT(memoryMap[ getIndirectAddress( ins.getInstructionOperator() ) ].getDataSigned());
state.setI(getIndirectAddress( ins.getInstructionOperator() ));
state.setS(getIndirectAddress( ins.getInstructionOperator() ));
state.incrementP();
//Ahora señalamos qué registros han cambiado
state.setRegisterChanged(ComputerRegister.A, true);
state.setRegisterChanged(ComputerRegister.T, true);
state.setRegisterChanged(ComputerRegister.I, true);
state.setRegisterChanged(ComputerRegister.S, true);
state.setRegisterChanged(ComputerRegister.P, true);
//Aquí mostramos las señales usadas en el transcurso de la ejecución
de la instrucción.
//Algunos setSignal los comento, pero solo para no repetir llamadas
iguales
//M(P) -> I
/*state.setSignal(ComputerSignal.SP, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);*/
//M(M(D)) ->A
state.setSignal(ComputerSignal.SD, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);
//state.setSignal(ComputerSignal.SD, true);
//state.setSignal(ComputerSignal.ES, true);
//state.setSignal(ComputerSignal.LECM, true);
//state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EO, true);
state.setSignal(ComputerSignal.MULTA, true);
state.setSignal(ComputerSignal.EA, true);
//P -> P+1
state.setSignal(ComputerSignal.INCP, true);
state.sendSignals();
case DIV:
}
catch(IndexOutOfBoundsException exception)
{
throw new Exception("MULI");
}
break;
try{
state.setA(state.getA() /
memoryMap[ins.getInstructionOperator()].getDataSigned());
state.setT(memoryMap[ins.getInstructionOperator()].getDataSigned());
//state.setI(ins.getDataSigned());
state.setS(ins.getInstructionOperator());
state.incrementP();
//Ahora señalamos qué registros han cambiado
state.setRegisterChanged(ComputerRegister.A, true);
state.setRegisterChanged(ComputerRegister.T, true);
//state.setRegisterChanged(ComputerRegister.I, true);
state.setRegisterChanged(ComputerRegister.S, true);
state.setRegisterChanged(ComputerRegister.P, true);
//Aquí mostramos las señales usadas en el transcurso de la ejecución
de la instrucción.
//Algunos setSignal los comento, pero solo para no repetir llamadas
iguales
//M(P) -> I
/*state.setSignal(ComputerSignal.SP, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);*/
//A+M(D) ->A
state.setSignal(ComputerSignal.SD, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EO, true);
state.setSignal(ComputerSignal.DIVA, true);
state.setSignal(ComputerSignal.EA, true);
//P -> P+1
state.setSignal(ComputerSignal.INCP, true);
180
state.sendSignals();
}
catch(IndexOutOfBoundsException exception)
{
throw new Exception("DIV");
}
break;
case DIVI:
try{
state.setA(state.getA() /
memoryMap[ getIndirectAddress( ins.getInstructionOperator() ) ].getDataSigned());
state.setT(memoryMap[ getIndirectAddress( ins.getInstructionOperator() ) ].getDataSigned());
state.setI(getIndirectAddress( ins.getInstructionOperator() ));
state.setS(getIndirectAddress( ins.getInstructionOperator() ));
state.incrementP();
//Ahora señalamos qué registros han cambiado
state.setRegisterChanged(ComputerRegister.A, true);
state.setRegisterChanged(ComputerRegister.T, true);
state.setRegisterChanged(ComputerRegister.I, true);
state.setRegisterChanged(ComputerRegister.S, true);
state.setRegisterChanged(ComputerRegister.P, true);
//Aquí mostramos las señales usadas en el transcurso de la ejecución
de la instrucción.
//Algunos setSignal los comento, pero solo para no repetir llamadas
iguales
//M(P) -> I
/*state.setSignal(ComputerSignal.SP, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);*/
//M(M(D)) ->A
state.setSignal(ComputerSignal.SD, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);
//state.setSignal(ComputerSignal.SD, true);
//state.setSignal(ComputerSignal.ES, true);
//state.setSignal(ComputerSignal.LECM, true);
//state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EO, true);
state.setSignal(ComputerSignal.DIVA, true);
state.setSignal(ComputerSignal.EA, true);
//P -> P+1
state.setSignal(ComputerSignal.INCP, true);
state.sendSignals();
case MOD:
}
catch(IndexOutOfBoundsException exception)
{
throw new Exception("DIVI");
}
break;
try{
state.setA(state.getA() %
memoryMap[ins.getInstructionOperator()].getDataSigned());
state.setT(memoryMap[ins.getInstructionOperator()].getDataSigned());
//state.setI(ins.getDataSigned());
state.setS(ins.getInstructionOperator());
state.incrementP();
//Ahora señalamos qué registros han cambiado
state.setRegisterChanged(ComputerRegister.A, true);
state.setRegisterChanged(ComputerRegister.T, true);
//state.setRegisterChanged(ComputerRegister.I, true);
state.setRegisterChanged(ComputerRegister.S, true);
state.setRegisterChanged(ComputerRegister.P, true);
//Aquí mostramos las señales usadas en el transcurso de la ejecución
de la instrucción.
//Algunos setSignal los comento, pero solo para no repetir llamadas
iguales
//M(P) -> I
/*state.setSignal(ComputerSignal.SP, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);*/
//A+M(D) ->A
state.setSignal(ComputerSignal.SD, true);
state.setSignal(ComputerSignal.ES, true);
181
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EO, true);
state.setSignal(ComputerSignal.MODA, true);
state.setSignal(ComputerSignal.EA, true);
//P -> P+1
state.setSignal(ComputerSignal.INCP, true);
state.sendSignals();
}
catch(IndexOutOfBoundsException exception)
{
throw new Exception("MOD");
}
break;
case MODI:
try{
state.setA(state.getA() %
memoryMap[ getIndirectAddress( ins.getInstructionOperator() ) ].getDataSigned());
state.setT(memoryMap[ getIndirectAddress( ins.getInstructionOperator() ) ].getDataSigned());
state.setI(getIndirectAddress( ins.getInstructionOperator() ));
state.setS(getIndirectAddress( ins.getInstructionOperator() ));
state.incrementP();
//Ahora señalamos qué registros han cambiado
state.setRegisterChanged(ComputerRegister.A, true);
state.setRegisterChanged(ComputerRegister.T, true);
state.setRegisterChanged(ComputerRegister.I, true);
state.setRegisterChanged(ComputerRegister.S, true);
state.setRegisterChanged(ComputerRegister.P, true);
//Aquí mostramos las señales usadas en el transcurso de la ejecución
de la instrucción.
//Algunos setSignal los comento, pero solo para no repetir llamadas
iguales
//M(P) -> I
/*state.setSignal(ComputerSignal.SP, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);*/
//M(M(D)) ->A
state.setSignal(ComputerSignal.SD, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);
//state.setSignal(ComputerSignal.SD, true);
//state.setSignal(ComputerSignal.ES, true);
//state.setSignal(ComputerSignal.LECM, true);
//state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EO, true);
state.setSignal(ComputerSignal.MODA, true);
state.setSignal(ComputerSignal.EA, true);
//P -> P+1
state.setSignal(ComputerSignal.INCP, true);
state.sendSignals();
case SAL:
}
catch(IndexOutOfBoundsException exception)
{
throw new Exception("MODI");
}
break;
try{
//state.setS(state.getP());
//state.setT(ins.getDataSigned());
//state.setI(ins.getDataSigned());
state.setP(ins.getInstructionOperator());
//Ahora señalamos qué registros han cambiado
//state.setRegisterChanged(ComputerRegister.T, true);
//state.setRegisterChanged(ComputerRegister.I, true);
//state.setRegisterChanged(ComputerRegister.S, true);
state.setRegisterChanged(ComputerRegister.P, true);
//Aquí mostramos las señales usadas en el transcurso de la ejecución
de la instrucción.
//Algunos setSignal los comento, pero solo para no repetir llamadas
iguales
//M(P) -> I
/*state.setSignal(ComputerSignal.SP, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);*/
182
//D -> P
state.setSignal(ComputerSignal.SD, true);
state.setSignal(ComputerSignal.EP, true);
state.sendSignals();
}
catch(IndexOutOfBoundsException exception)
{
throw new Exception("SAL");
}
break;
case SALI:
try{
state.setS(ins.getInstructionOperator());
state.setI(getIndirectAddress( ins.getInstructionOperator() ));
state.setT(getIndirectAddress( ins.getInstructionOperator() ));
state.setP( getIndirectAddress( ins.getInstructionOperator() ) );
//Ahora señalamos qué registros han cambiado
state.setRegisterChanged(ComputerRegister.T, true);
state.setRegisterChanged(ComputerRegister.I, true);
state.setRegisterChanged(ComputerRegister.S, true);
state.setRegisterChanged(ComputerRegister.P, true);
//Aquí mostramos las señales usadas en el transcurso de la ejecución
de la instrucción.
//Algunos setSignal los comento, pero solo para no repetir llamadas
iguales
//M(P) -> I
/*state.setSignal(ComputerSignal.SP, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);*/
//M(D) -> P
state.setSignal(ComputerSignal.SD, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);
//state.setSignal(ComputerSignal.SD, true);
state.setSignal(ComputerSignal.EP, true);
state.sendSignals();
case SAN:
}
catch(IndexOutOfBoundsException exception)
{
throw new Exception("SALI");
}
break;
try{
//state.setS(state.getP());
//state.setT(ins.getDataSigned());
//state.setI(ins.getDataSigned());
if(state.getA() < 0)
{
state.setP(ins.getInstructionOperator());
//Ahora señalamos qué registros han cambiado
//state.setRegisterChanged(ComputerRegister.T, true);
//state.setRegisterChanged(ComputerRegister.I, true);
//state.setRegisterChanged(ComputerRegister.S, true);
state.setRegisterChanged(ComputerRegister.P, true);
//Aquí mostramos las señales usadas en el transcurso de la
ejecución de la instrucción.
//Algunos setSignal los comento, pero solo para no repetir
llamadas iguales
//M(P) -> I
/*state.setSignal(ComputerSignal.SP, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);*/
//D -> P
state.setSignal(ComputerSignal.SD, true);
state.setSignal(ComputerSignal.EP, true);
state.sendSignals();
}
else
{
state.incrementP();
//Ahora señalamos qué registros han cambiado
//state.setRegisterChanged(ComputerRegister.T, true);
//state.setRegisterChanged(ComputerRegister.I, true);
//state.setRegisterChanged(ComputerRegister.S, true);
state.setRegisterChanged(ComputerRegister.P, true);
//Aquí mostramos las señales usadas en el transcurso de la
ejecución de la instrucción.
//Algunos setSignal los comento, pero solo para no repetir
183
llamadas iguales
//M(P) -> I
/*state.setSignal(ComputerSignal.SP, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);*/
//P -> P+1
state.setSignal(ComputerSignal.INCP, true);
state.sendSignals();
}
}
catch(IndexOutOfBoundsException exception)
{
throw new Exception("SAN");
}
break;
case SANI:
try{
if(state.getA() < 0)
{
state.setS(ins.getInstructionOperator());
state.setI(getIndirectAddress( ins.getInstructionOperator()
));
state.setT(getIndirectAddress( ins.getInstructionOperator()
));
state.setP( getIndirectAddress( ins.getInstructionOperator() ) );
//Ahora señalamos qué registros han cambiado
state.setRegisterChanged(ComputerRegister.T, true);
state.setRegisterChanged(ComputerRegister.I, true);
state.setRegisterChanged(ComputerRegister.S, true);
state.setRegisterChanged(ComputerRegister.P, true);
//Aquí mostramos las señales usadas en el transcurso de la
ejecución de la instrucción.
//Algunos setSignal los comento, pero solo para no repetir
llamadas iguales
//M(P) -> I
/*state.setSignal(ComputerSignal.SP, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);*/
//M(D) -> P
state.setSignal(ComputerSignal.SD, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);
//state.setSignal(ComputerSignal.SD, true);
state.setSignal(ComputerSignal.EP, true);
state.sendSignals();
}
else
{
/*state.setS(state.getP());
state.setT(ins.getDataSigned());
state.setI(ins.getDataSigned());*/
state.incrementP();
//Ahora señalamos qué registros han cambiado
/*state.setRegisterChanged(ComputerRegister.T, true);
state.setRegisterChanged(ComputerRegister.I, true);
state.setRegisterChanged(ComputerRegister.S, true);*/
state.setRegisterChanged(ComputerRegister.P, true);
//Aquí mostramos las señales usadas en el transcurso de la
ejecución de la instrucción.
//Algunos setSignal los comento, pero solo para no repetir
llamadas iguales
//M(P) -> I
/*state.setSignal(ComputerSignal.SP, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);*/
//P -> P+1
state.setSignal(ComputerSignal.INCP, true);
state.sendSignals();
case SAC:
}
}
catch(IndexOutOfBoundsException exception)
{
throw new Exception("SANI");
}
break;
184
try{
/*state.setS(state.getP());
state.setT(ins.getDataSigned());
state.setI(ins.getDataSigned());*/
//Ahora señalamos qué registros han cambiado
/*state.setRegisterChanged(ComputerRegister.T, true);
state.setRegisterChanged(ComputerRegister.I, true);
state.setRegisterChanged(ComputerRegister.S, true);*/
state.setRegisterChanged(ComputerRegister.P, true);
if(state.getA() == 0)
{
state.setP(ins.getInstructionOperator());
//Aquí mostramos las señales usadas en el transcurso de la
ejecución de la instrucción.
//Algunos setSignal los comento, pero solo para no repetir
llamadas iguales
//M(P) -> I
/*state.setSignal(ComputerSignal.SP, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);*/
//D -> P
state.setSignal(ComputerSignal.SD, true);
state.setSignal(ComputerSignal.EP, true);
state.sendSignals();
}
else
{
state.incrementP();
//Aquí mostramos las señales usadas en el transcurso de la
ejecución de la instrucción.
//Algunos setSignal los comento, pero solo para no repetir
llamadas iguales
//M(P) -> I
/*state.setSignal(ComputerSignal.SP, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);*/
//P -> P+1
state.setSignal(ComputerSignal.INCP, true);
state.sendSignals();
}
}
catch(IndexOutOfBoundsException exception)
{
throw new Exception("SAC");
}
break;
case SACI:
try{
//Ahora señalamos qué registros han cambiado
if(state.getA() == 0)
{
state.setRegisterChanged(ComputerRegister.T,
state.setRegisterChanged(ComputerRegister.I,
state.setRegisterChanged(ComputerRegister.S,
state.setRegisterChanged(ComputerRegister.P,
true);
true);
true);
true);
state.setS(ins.getInstructionOperator());
state.setI(getIndirectAddress( ins.getInstructionOperator()
));
state.setT(getIndirectAddress( ins.getInstructionOperator()
));
state.setP( getIndirectAddress( ins.getInstructionOperator() ) );
//Aquí mostramos las señales usadas en el transcurso de la
ejecución de la instrucción.
//Algunos setSignal los comento, pero solo para no repetir
llamadas iguales
//M(P) -> I
/*state.setSignal(ComputerSignal.SP, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);*/
//M(D) -> P
state.setSignal(ComputerSignal.SD, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
185
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);
//state.setSignal(ComputerSignal.SD, true);
state.setSignal(ComputerSignal.EP, true);
state.sendSignals();
}
else
{
/*state.setRegisterChanged(ComputerRegister.T, true);
state.setRegisterChanged(ComputerRegister.I, true);
state.setRegisterChanged(ComputerRegister.S, true);*/
state.setRegisterChanged(ComputerRegister.P, true);
/*state.setS(state.getP());
state.setT(ins.getDataSigned());
state.setI(ins.getDataSigned());*/
state.incrementP();
//Aquí mostramos las señales usadas en el transcurso de la
ejecución de la instrucción.
//Algunos setSignal los comento, pero solo para no repetir
llamadas iguales
//M(P) -> I
/*state.setSignal(ComputerSignal.SP, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);*/
//P -> P+1
state.setSignal(ComputerSignal.INCP, true);
state.sendSignals();
case SAP:
}
}
catch(IndexOutOfBoundsException exception)
{
throw new Exception("SACI");
}
break;
try{
/*state.setS(state.getP());
state.setT(ins.getDataSigned());
state.setI(ins.getDataSigned());*/
//Ahora señalamos qué registros han cambiado
/*state.setRegisterChanged(ComputerRegister.T, true);
state.setRegisterChanged(ComputerRegister.I, true);
state.setRegisterChanged(ComputerRegister.S, true);*/
state.setRegisterChanged(ComputerRegister.P, true);
if(state.getA() > 0)
{
state.setP(ins.getInstructionOperator());
//Aquí mostramos las señales usadas en el transcurso de la
ejecución de la instrucción.
//Algunos setSignal los comento, pero solo para no repetir
llamadas iguales
//M(P) -> I
/*state.setSignal(ComputerSignal.SP, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);*/
//D -> P
state.setSignal(ComputerSignal.SD, true);
state.setSignal(ComputerSignal.EP, true);
state.sendSignals();
}
else
{
state.incrementP();
//Aquí mostramos las señales usadas en el transcurso de la
ejecución de la instrucción.
//Algunos setSignal los comento, pero solo para no repetir
llamadas iguales
//M(P) -> I
/*state.setSignal(ComputerSignal.SP, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);*/
//P -> P+1
state.setSignal(ComputerSignal.INCP, true);
state.sendSignals();
}
}
186
catch(IndexOutOfBoundsException exception)
{
throw new Exception("SAP");
}
break;
case SAPI:
try{
if(state.getA() > 0)
{
state.setS(ins.getInstructionOperator());
state.setI(getIndirectAddress( ins.getInstructionOperator()
));
state.setT(getIndirectAddress( ins.getInstructionOperator()
));
state.setP( getIndirectAddress( ins.getInstructionOperator() ) );
//Ahora señalamos qué registros han cambiado
state.setRegisterChanged(ComputerRegister.T,
state.setRegisterChanged(ComputerRegister.I,
state.setRegisterChanged(ComputerRegister.S,
state.setRegisterChanged(ComputerRegister.P,
true);
true);
true);
true);
//Aquí mostramos las señales usadas en el transcurso de la
ejecución de la instrucción.
//Algunos setSignal los comento, pero solo para no repetir
llamadas iguales
//M(P) -> I
/*state.setSignal(ComputerSignal.SP, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);*/
//M(D) -> P
state.setSignal(ComputerSignal.SD, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);
//state.setSignal(ComputerSignal.SD, true);
state.setSignal(ComputerSignal.EP, true);
state.sendSignals();
}
else
{
/*state.setS(state.getP());
state.setT(ins.getDataSigned());
state.setI(ins.getDataSigned());*/
state.incrementP();
//Ahora señalamos qué registros han cambiado
/*state.setRegisterChanged(ComputerRegister.T, true);
state.setRegisterChanged(ComputerRegister.I, true);
state.setRegisterChanged(ComputerRegister.S, true);*/
state.setRegisterChanged(ComputerRegister.P, true);
//Aquí mostramos las señales usadas en el transcurso de la
ejecución de la instrucción.
//Algunos setSignal los comento, pero solo para no repetir
llamadas iguales
//M(P) -> I
/*state.setSignal(ComputerSignal.SP, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);*/
//P -> P+1
state.setSignal(ComputerSignal.INCP, true);
state.sendSignals();
case ECA:
}
}
catch(IndexOutOfBoundsException exception)
{
throw new Exception("SAPI");
}
break;
try{
state.setE(memoryMap[ins.getInstructionOperator()].getDataSigned());
state.setT(state.getE());
//state.setI(ins.getDataSigned());
state.setS(ins.getInstructionOperator());
187
state.getListener().writeCharacterToScreen();
state.incrementP();
//Ahora señalamos qué registros han cambiado
state.setRegisterChanged(ComputerRegister.E, true);
state.setRegisterChanged(ComputerRegister.T, true);
//state.setRegisterChanged(ComputerRegister.I, true);
state.setRegisterChanged(ComputerRegister.S, true);
state.setRegisterChanged(ComputerRegister.P, true);
//Aquí mostramos las señales usadas en el transcurso de la ejecución
de la instrucción.
//Algunos setSignal los comento, pero solo para no repetir llamadas
iguales
//M(P) -> I
/*state.setSignal(ComputerSignal.SP, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);*/
//M(D) ->E
state.setSignal(ComputerSignal.SD, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EE, true);
state.setSignal(ComputerSignal.ESCP, true);
//P -> P+1
state.setSignal(ComputerSignal.INCP, true);
state.sendSignals();
}
catch(IndexOutOfBoundsException exception)
{
throw new Exception("ECA");
}
break;
case ECAI:
try{
state.setE(memoryMap[ getIndirectAddress( ins.getInstructionOperator() ) ].getDataSigned());
state.setT(state.getE());
state.setI(getIndirectAddress( ins.getInstructionOperator() ));
state.setS(getIndirectAddress( ins.getInstructionOperator() ));
state.getListener().writeCharacterToScreen();
state.incrementP();
//Ahora señalamos qué registros han cambiado
state.setRegisterChanged(ComputerRegister.E, true);
state.setRegisterChanged(ComputerRegister.T, true);
state.setRegisterChanged(ComputerRegister.I, true);
state.setRegisterChanged(ComputerRegister.S, true);
state.setRegisterChanged(ComputerRegister.P, true);
//Aquí mostramos las señales usadas en el transcurso de la ejecución
de la instrucción.
//Algunos setSignal los comento, pero solo para no repetir llamadas
iguales
//M(P) -> I
/*state.setSignal(ComputerSignal.SP, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);*/
//M(M(D)) ->A
state.setSignal(ComputerSignal.SD, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);
//state.setSignal(ComputerSignal.SD, true);
//state.setSignal(ComputerSignal.ES, true);
//state.setSignal(ComputerSignal.LECM, true);
//state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EE, true);
state.setSignal(ComputerSignal.ESCP, true);
//P -> P+1
state.setSignal(ComputerSignal.INCP, true);
state.sendSignals();
case LCA:
}
catch(IndexOutOfBoundsException exception)
{
throw new Exception("ECAI");
}
break;
try{
/**
* Before executing this instruction,
188
* the input from the keyboard should have been saved into register
E.
*/
int operator = ins.getInstructionOperator();
memoryMap[operator].setInstructionSigned(state.getE());
state.setT(state.getE());
//state.setI(ins.getDataSigned());
state.setS(operator);
state.getListener().memoryChanged(memoryMap[operator]);
state.setChangedMemory(memoryMap[operator].getAddressLocation());
state.incrementP();
//Ahora señalamos qué registros han cambiado
state.setRegisterChanged(ComputerRegister.T, true);
//state.setRegisterChanged(ComputerRegister.I, true);
state.setRegisterChanged(ComputerRegister.S, true);
state.setRegisterChanged(ComputerRegister.P, true);
//Aquí mostramos las señales usadas en el transcurso de la ejecución
de la instrucción.
//Algunos setSignal los comento, pero solo para no repetir llamadas
iguales
//M(P) -> I
/*state.setSignal(ComputerSignal.SP, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);*/
//E -> M(D)
state.setSignal(ComputerSignal.SD, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LEET, true);
state.setSignal(ComputerSignal.SE, true);
state.setSignal(ComputerSignal.ET, true);
state.setSignal(ComputerSignal.ESCM, true);
//P -> P+1
state.setSignal(ComputerSignal.INCP, true);
state.sendSignals();
}
catch(IndexOutOfBoundsException exception)
{
throw new Exception("LCA");
}
break;
case LCAI:
try{
/**
* Before executing this instruction,
* the input from the keyboard should have been saved into register
E.
*/
int operator = getIndirectAddress( ins.getInstructionOperator() );
memoryMap[operator].setInstructionSigned(state.getE());
state.setT(state.getE());
state.setI(operator);
state.setS(operator);
state.getListener().memoryChanged(memoryMap[operator]);
state.setChangedMemory(memoryMap[operator].getAddressLocation());
state.incrementP();
//Ahora señalamos qué registros han cambiado
state.setRegisterChanged(ComputerRegister.T, true);
state.setRegisterChanged(ComputerRegister.I, true);
state.setRegisterChanged(ComputerRegister.S, true);
state.setRegisterChanged(ComputerRegister.P, true);
//Aquí mostramos las señales usadas en el transcurso de la ejecución
de la instrucción.
//Algunos setSignal los comento, pero solo para no repetir llamadas
iguales
//M(P) -> I
/*state.setSignal(ComputerSignal.SP, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);*/
//A -> M(M(D))
state.setSignal(ComputerSignal.SD, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);
//state.setSignal(ComputerSignal.SD, true);
//state.setSignal(ComputerSignal.ES, true);
189
state.setSignal(ComputerSignal.LEET, true);
state.setSignal(ComputerSignal.SE, true);
state.setSignal(ComputerSignal.ET, true);
state.setSignal(ComputerSignal.ESCM, true);
//P -> P+1
state.setSignal(ComputerSignal.INCP, true);
state.sendSignals();
}
catch(IndexOutOfBoundsException exception)
{
throw new Exception("LCAI");
}
break;
}
}
else
{
throw new Exception("The emulator arrived to a memory address with no instruction. The
memory map may have not ben properly initialized");
}
semiStep = First_Semistep;
}
}
//Ya hemos ejecutado la instrucción así que apagamos el semáforo.
trafficLight = false;
return getState();
}
/**
* @brief Método que ejecuta la siguiente instrucción.
* @return
* @throws Exception
*/
public ComputerState executeNextInstruction() throws Exception
{
//Usamos el semáforo trafficLight para que no se puedan realizar
//llamadas en paralelo/concurrentes a esta instrucción.
if(trafficLight == false)
{
trafficLight = true;
//Recogemos la instrucción a ejecutar
Instruction ins = memoryMap[state.getP()];
//Marcamos todos los registros y señales como no modificados
state.resetSignalsRegisters();
state.setSemiState(First_Semistep);
if(ins.isInstruction() == true)
{
switch(ins.getOperationCode()) //Elegimos qué operación ejecutar según el código de operación.
{
case ALT:
break;
case ALM:
try{
/*int operator = ins.getInstructionOperator();
state.setT(memoryMap[operator].getDataSigned());
state.setI(memoryMap[operator].getDataSigned());
state.setS(state.getP());
//Ahora señalamos qué registros han cambiado
state.setRegisterChanged(ComputerRegister.T, true);
state.setRegisterChanged(ComputerRegister.I, true);
state.setRegisterChanged(ComputerRegister.S, true);
state.setRegisterChanged(ComputerRegister.P, true);
//Aquí mostramos las señales usadas en el transcurso de la ejecución de la
instrucción.
//M(P) -> I equivalente a: P -> S. M(S) -> T. T -> I.
state.setSignal(ComputerSignal.SP, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);*/
int operator = ins.getInstructionOperator();
memoryMap[operator].setInstructionSigned(state.getA());
state.getListener().memoryChanged(memoryMap[operator]);
state.setChangedMemory(memoryMap[operator].getAddressLocation());
state.setT(state.getA());
190
state.setI(ins.getDataSigned());
state.setS(operator);
state.incrementP();
//Ahora señalamos qué registros han cambiado
state.setRegisterChanged(ComputerRegister.T, true);
state.setRegisterChanged(ComputerRegister.I, true);
state.setRegisterChanged(ComputerRegister.S, true);
state.setRegisterChanged(ComputerRegister.P, true);
//Aquí mostramos las señales usadas en el transcurso de la ejecución de la
instrucción.
//Algunos setSignal los comento, pero solo para no repetir llamadas iguales
//M(P) -> I equivalente a: P -> S. M(S) -> T. T -> I.
state.setSignal(ComputerSignal.SP, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);
//A -> M(D)
state.setSignal(ComputerSignal.SD, true);
//state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.SA, true);
state.setSignal(ComputerSignal.ET, true);
state.setSignal(ComputerSignal.ESCM, true);
//P -> P+1
state.setSignal(ComputerSignal.INCP, true);
state.sendSignals();
}
catch(IndexOutOfBoundsException exception)
{
throw new Exception("ALM");
}
break;
case ALMI:
try{
int operator = getIndirectAddress( ins.getInstructionOperator() );
memoryMap[operator].setInstructionSigned(state.getA());
state.setChangedMemory(memoryMap[operator].getAddressLocation());
state.getListener().memoryChanged(memoryMap[operator]);
state.setT(state.getA());
state.setI(operator);
state.setS(operator);
state.incrementP();
//Ahora señalamos qué registros han cambiado
state.setRegisterChanged(ComputerRegister.T, true);
state.setRegisterChanged(ComputerRegister.I, true);
state.setRegisterChanged(ComputerRegister.S, true);
state.setRegisterChanged(ComputerRegister.P, true);
//Aquí mostramos las señales usadas en el transcurso de la ejecución de la
instrucción.
//Algunos setSignal los comento, pero solo para no repetir llamadas iguales
//M(P) -> I
state.setSignal(ComputerSignal.SP, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);
//A -> M(M(D))
state.setSignal(ComputerSignal.SD, true);
//state.setSignal(ComputerSignal.ES, true);
//state.setSignal(ComputerSignal.LECM, true);
//state.setSignal(ComputerSignal.ST, true);
//state.setSignal(ComputerSignal.EI, true);
//state.setSignal(ComputerSignal.SD, true);
//state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.SA, true);
state.setSignal(ComputerSignal.ET, true);
state.setSignal(ComputerSignal.ESCM, true);
//P -> P+1
state.setSignal(ComputerSignal.INCP, true);
state.sendSignals();
case CAR:
}
catch(IndexOutOfBoundsException exception)
{
throw new Exception("ALMI");
}
break;
try{
state.setA(memoryMap[ins.getInstructionOperator()].getDataSigned());
state.setT(state.getA());
191
state.setI(ins.getDataSigned());
state.setS(ins.getInstructionOperator());
state.incrementP();
//Ahora señalamos qué registros han cambiado
state.setRegisterChanged(ComputerRegister.A, true);
state.setRegisterChanged(ComputerRegister.T, true);
state.setRegisterChanged(ComputerRegister.I, true);
state.setRegisterChanged(ComputerRegister.S, true);
state.setRegisterChanged(ComputerRegister.P, true);
//Aquí mostramos las señales usadas en el transcurso de la ejecución de la
instrucción.
//Algunos setSignal los comento, pero solo para no repetir llamadas iguales
//M(P) -> I
state.setSignal(ComputerSignal.SP, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);
//M(D) ->A
state.setSignal(ComputerSignal.SD, true);
//state.setSignal(ComputerSignal.ES, true);
//state.setSignal(ComputerSignal.LECM, true);
//state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EO, true);
state.setSignal(ComputerSignal.EA, true);
//P -> P+1
state.setSignal(ComputerSignal.INCP, true);
state.sendSignals();
}
catch(IndexOutOfBoundsException exception)
{
throw new Exception("CAR");
}
break;
case CARI:
try{
state.setA(memoryMap[ getIndirectAddress( ins.getInstructionOperator() ) ].getDataSigned());
state.setT(state.getA());
state.setI(getIndirectAddress( ins.getInstructionOperator() ));
state.setS(getIndirectAddress( ins.getInstructionOperator() ));
state.incrementP();
//Ahora señalamos qué registros han cambiado
state.setRegisterChanged(ComputerRegister.A, true);
state.setRegisterChanged(ComputerRegister.T, true);
state.setRegisterChanged(ComputerRegister.I, true);
state.setRegisterChanged(ComputerRegister.S, true);
state.setRegisterChanged(ComputerRegister.P, true);
//Aquí mostramos las señales usadas en el transcurso de la ejecución de la
instrucción.
//Algunos setSignal los comento, pero solo para no repetir llamadas iguales
//M(P) -> I
state.setSignal(ComputerSignal.SP, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);
//M(M(D)) ->A
state.setSignal(ComputerSignal.SD, true);
//state.setSignal(ComputerSignal.ES, true);
//state.setSignal(ComputerSignal.LECM, true);
//state.setSignal(ComputerSignal.ST, true);
//state.setSignal(ComputerSignal.EI, true);
//state.setSignal(ComputerSignal.SD, true);
//state.setSignal(ComputerSignal.ES, true);
//state.setSignal(ComputerSignal.LECM, true);
//state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EO, true);
state.setSignal(ComputerSignal.EA, true);
//P -> P+1
state.setSignal(ComputerSignal.INCP, true);
state.sendSignals();
case ESC:
}
catch(IndexOutOfBoundsException exception)
{
throw new Exception("CARI");
}
break;
try{
state.setE(memoryMap[ins.getInstructionOperator()].getDataSigned());
state.setT(state.getE());
192
state.setI(ins.getDataSigned());
state.setS(ins.getInstructionOperator());
state.getListener().writeNumberToScreen();
state.incrementP();
//Ahora señalamos qué registros han cambiado
state.setRegisterChanged(ComputerRegister.E, true);
state.setRegisterChanged(ComputerRegister.T, true);
state.setRegisterChanged(ComputerRegister.I, true);
state.setRegisterChanged(ComputerRegister.S, true);
state.setRegisterChanged(ComputerRegister.P, true);
//Aquí mostramos las señales usadas en el transcurso de la ejecución de la
instrucción.
//Algunos setSignal los comento, pero solo para no repetir llamadas iguales
//M(P) -> I
state.setSignal(ComputerSignal.SP, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);
//M(D) ->E
state.setSignal(ComputerSignal.SD, true);
//state.setSignal(ComputerSignal.ES, true);
//state.setSignal(ComputerSignal.LECM, true);
//state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EE, true);
state.setSignal(ComputerSignal.ESCP, true);
//P -> P+1
state.setSignal(ComputerSignal.INCP, true);
state.sendSignals();
}
catch(IndexOutOfBoundsException exception)
{
throw new Exception("ESC");
}
break;
case ESCI:
try{
state.setE(memoryMap[ getIndirectAddress( ins.getInstructionOperator() ) ].getDataSigned());
state.setT(state.getE());
state.setI(getIndirectAddress( ins.getInstructionOperator() ));
state.setS(getIndirectAddress( ins.getInstructionOperator() ));
state.getListener().writeNumberToScreen();
state.incrementP();
//Ahora señalamos qué registros han cambiado
state.setRegisterChanged(ComputerRegister.E, true);
state.setRegisterChanged(ComputerRegister.T, true);
state.setRegisterChanged(ComputerRegister.I, true);
state.setRegisterChanged(ComputerRegister.S, true);
state.setRegisterChanged(ComputerRegister.P, true);
//Aquí mostramos las señales usadas en el transcurso de la ejecución de la
instrucción.
//Algunos setSignal los comento, pero solo para no repetir llamadas iguales
//M(P) -> I
state.setSignal(ComputerSignal.SP, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);
//M(M(D)) ->A
state.setSignal(ComputerSignal.SD, true);
//state.setSignal(ComputerSignal.ES, true);
//state.setSignal(ComputerSignal.LECM, true);
//state.setSignal(ComputerSignal.ST, true);
//state.setSignal(ComputerSignal.EI, true);
//state.setSignal(ComputerSignal.SD, true);
//state.setSignal(ComputerSignal.ES, true);
//state.setSignal(ComputerSignal.LECM, true);
//state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EE, true);
state.setSignal(ComputerSignal.ESCP, true);
//P -> P+1
state.setSignal(ComputerSignal.INCP, true);
state.sendSignals();
case LEE:
}
catch(IndexOutOfBoundsException exception)
{
throw new Exception("ESCI");
}
break;
try{
/**
* Before executing this instruction,
193
* the input from the keyboard should have been saved into register E.
*/
int operator = ins.getInstructionOperator();
memoryMap[operator].setInstructionSigned(state.getE());
state.setT(state.getE());
state.setI(ins.getDataSigned());
state.setS(operator);
state.getListener().memoryChanged(memoryMap[operator]);
state.setChangedMemory(memoryMap[operator].getAddressLocation());
state.incrementP();
//Ahora señalamos qué registros han cambiado
state.setRegisterChanged(ComputerRegister.T, true);
state.setRegisterChanged(ComputerRegister.I, true);
state.setRegisterChanged(ComputerRegister.S, true);
state.setRegisterChanged(ComputerRegister.P, true);
//Aquí mostramos las señales usadas en el transcurso de la ejecución de la
instrucción.
//Algunos setSignal los comento, pero solo para no repetir llamadas iguales
//M(P) -> I
state.setSignal(ComputerSignal.SP, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);
//E -> M(D)
state.setSignal(ComputerSignal.SD, true);
//state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LEET, true);
state.setSignal(ComputerSignal.SE, true);
state.setSignal(ComputerSignal.ET, true);
state.setSignal(ComputerSignal.ESCM, true);
//P -> P+1
state.setSignal(ComputerSignal.INCP, true);
state.sendSignals();
}
catch(IndexOutOfBoundsException exception)
{
throw new Exception("LEE");
}
break;
case LEEI:
try{
/**
* Before executing this instruction,
* the input from the keyboard should have been saved into register E.
*/
int operator = getIndirectAddress( ins.getInstructionOperator() );
memoryMap[operator].setInstructionSigned(state.getE());
state.setT(state.getE());
state.setI(operator);
state.setS(operator);
state.getListener().memoryChanged(memoryMap[operator]);
state.setChangedMemory(memoryMap[operator].getAddressLocation());
state.incrementP();
//Ahora señalamos qué registros han cambiado
state.setRegisterChanged(ComputerRegister.T, true);
state.setRegisterChanged(ComputerRegister.I, true);
state.setRegisterChanged(ComputerRegister.S, true);
state.setRegisterChanged(ComputerRegister.P, true);
//Aquí mostramos las señales usadas en el transcurso de la ejecución de la
instrucción.
//Algunos setSignal los comento, pero solo para no repetir llamadas iguales
//M(P) -> I
state.setSignal(ComputerSignal.SP, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);
//A -> M(M(D))
state.setSignal(ComputerSignal.SD, true);
//state.setSignal(ComputerSignal.ES, true);
//state.setSignal(ComputerSignal.LECM, true);
//state.setSignal(ComputerSignal.ST, true);
//state.setSignal(ComputerSignal.EI, true);
//state.setSignal(ComputerSignal.SD, true);
//state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LEET, true);
state.setSignal(ComputerSignal.SE, true);
state.setSignal(ComputerSignal.ET, true);
state.setSignal(ComputerSignal.ESCM, true);
194
//P -> P+1
state.setSignal(ComputerSignal.INCP, true);
state.sendSignals();
case SUM:
}
catch(IndexOutOfBoundsException exception)
{
throw new Exception("LEEI");
}
break;
try{
state.setA(state.getA() +
memoryMap[ins.getInstructionOperator()].getDataSigned());
state.setT(memoryMap[ins.getInstructionOperator()].getDataSigned());
state.setI(ins.getDataSigned());
state.setS(ins.getInstructionOperator());
state.incrementP();
//Ahora señalamos qué registros han cambiado
state.setRegisterChanged(ComputerRegister.A, true);
state.setRegisterChanged(ComputerRegister.T, true);
state.setRegisterChanged(ComputerRegister.I, true);
state.setRegisterChanged(ComputerRegister.S, true);
state.setRegisterChanged(ComputerRegister.P, true);
//Aquí mostramos las señales usadas en el transcurso de la ejecución de la
instrucción.
//Algunos setSignal los comento, pero solo para no repetir llamadas iguales
//M(P) -> I
state.setSignal(ComputerSignal.SP, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);
//A+M(D) ->A
state.setSignal(ComputerSignal.SD, true);
//state.setSignal(ComputerSignal.ES, true);
//state.setSignal(ComputerSignal.LECM, true);
//state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EO, true);
state.setSignal(ComputerSignal.SUMA, true);
state.setSignal(ComputerSignal.EA, true);
//P -> P+1
state.setSignal(ComputerSignal.INCP, true);
state.sendSignals();
}
catch(IndexOutOfBoundsException exception)
{
throw new Exception("SUM");
}
break;
case SUMI:
try{
state.setA(state.getA() +
memoryMap[ getIndirectAddress( ins.getInstructionOperator()
) ].getDataSigned());
state.setT(memoryMap[ getIndirectAddress( ins.getInstructionOperator() ) ].getDataSigned());
state.setI(getIndirectAddress( ins.getInstructionOperator() ));
state.setS(getIndirectAddress( ins.getInstructionOperator() ));
state.incrementP();
//Ahora señalamos qué registros han cambiado
state.setRegisterChanged(ComputerRegister.A, true);
state.setRegisterChanged(ComputerRegister.T, true);
state.setRegisterChanged(ComputerRegister.I, true);
state.setRegisterChanged(ComputerRegister.S, true);
state.setRegisterChanged(ComputerRegister.P, true);
//Aquí mostramos las señales usadas en el transcurso de la ejecución de la
instrucción.
//Algunos setSignal los comento, pero solo para no repetir llamadas iguales
//M(P) -> I
state.setSignal(ComputerSignal.SP, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);
//M(M(D)) ->A
state.setSignal(ComputerSignal.SD, true);
//state.setSignal(ComputerSignal.ES, true);
//state.setSignal(ComputerSignal.LECM, true);
//state.setSignal(ComputerSignal.ST, true);
//state.setSignal(ComputerSignal.EI, true);
//state.setSignal(ComputerSignal.SD, true);
//state.setSignal(ComputerSignal.ES, true);
//state.setSignal(ComputerSignal.LECM, true);
195
//state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EO, true);
state.setSignal(ComputerSignal.SUMA, true);
state.setSignal(ComputerSignal.EA, true);
//P -> P+1
state.setSignal(ComputerSignal.INCP, true);
state.sendSignals();
case RES:
}
catch(IndexOutOfBoundsException exception)
{
throw new Exception("SUMI");
}
break;
try{
state.setA(state.getA() -
memoryMap[ins.getInstructionOperator()].getDataSigned());
state.setT(memoryMap[ins.getInstructionOperator()].getDataSigned());
state.setI(ins.getDataSigned());
state.setS(ins.getInstructionOperator());
state.incrementP();
//Ahora señalamos qué registros han cambiado
state.setRegisterChanged(ComputerRegister.A, true);
state.setRegisterChanged(ComputerRegister.T, true);
state.setRegisterChanged(ComputerRegister.I, true);
state.setRegisterChanged(ComputerRegister.S, true);
state.setRegisterChanged(ComputerRegister.P, true);
//Aquí mostramos las señales usadas en el transcurso de la ejecución de la
instrucción.
//Algunos setSignal los comento, pero solo para no repetir llamadas iguales
//M(P) -> I
state.setSignal(ComputerSignal.SP, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);
//A+M(D) ->A
state.setSignal(ComputerSignal.SD, true);
//state.setSignal(ComputerSignal.ES, true);
//state.setSignal(ComputerSignal.LECM, true);
//state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EO, true);
state.setSignal(ComputerSignal.RESA, true);
state.setSignal(ComputerSignal.EA, true);
//P -> P+1
state.setSignal(ComputerSignal.INCP, true);
state.sendSignals();
}
catch(IndexOutOfBoundsException exception)
{
throw new Exception("RES");
}
break;
case RESI:
try{
state.setA(state.getA() memoryMap[ getIndirectAddress( ins.getInstructionOperator()
) ].getDataSigned());
state.setT(memoryMap[ getIndirectAddress( ins.getInstructionOperator() ) ].getDataSigned());
state.setI(getIndirectAddress( ins.getInstructionOperator() ));
state.setS(getIndirectAddress( ins.getInstructionOperator() ));
state.incrementP();
//Ahora señalamos qué registros han cambiado
state.setRegisterChanged(ComputerRegister.A, true);
state.setRegisterChanged(ComputerRegister.T, true);
state.setRegisterChanged(ComputerRegister.I, true);
state.setRegisterChanged(ComputerRegister.S, true);
state.setRegisterChanged(ComputerRegister.P, true);
//Aquí mostramos las señales usadas en el transcurso de la ejecución de la
instrucción.
//Algunos setSignal los comento, pero solo para no repetir llamadas iguales
//M(P) -> I
state.setSignal(ComputerSignal.SP, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);
//M(M(D)) ->A
state.setSignal(ComputerSignal.SD, true);
//state.setSignal(ComputerSignal.ES, true);
196
//state.setSignal(ComputerSignal.LECM, true);
//state.setSignal(ComputerSignal.ST, true);
//state.setSignal(ComputerSignal.EI, true);
//state.setSignal(ComputerSignal.SD, true);
//state.setSignal(ComputerSignal.ES, true);
//state.setSignal(ComputerSignal.LECM, true);
//state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EO, true);
state.setSignal(ComputerSignal.RESA, true);
state.setSignal(ComputerSignal.EA, true);
//P -> P+1
state.setSignal(ComputerSignal.INCP, true);
state.sendSignals();
case MUL:
}
catch(IndexOutOfBoundsException exception)
{
throw new Exception("RESI");
}
break;
try{
state.setA(state.getA() *
memoryMap[ins.getInstructionOperator()].getDataSigned());
state.setT(memoryMap[ins.getInstructionOperator()].getDataSigned());
state.setI(ins.getDataSigned());
state.setS(ins.getInstructionOperator());
state.incrementP();
//Ahora señalamos qué registros han cambiado
state.setRegisterChanged(ComputerRegister.A, true);
state.setRegisterChanged(ComputerRegister.T, true);
state.setRegisterChanged(ComputerRegister.I, true);
state.setRegisterChanged(ComputerRegister.S, true);
state.setRegisterChanged(ComputerRegister.P, true);
//Aquí mostramos las señales usadas en el transcurso de la ejecución de la
instrucción.
//Algunos setSignal los comento, pero solo para no repetir llamadas iguales
//M(P) -> I
state.setSignal(ComputerSignal.SP, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);
//A+M(D) ->A
state.setSignal(ComputerSignal.SD, true);
//state.setSignal(ComputerSignal.ES, true);
//state.setSignal(ComputerSignal.LECM, true);
//state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EO, true);
state.setSignal(ComputerSignal.MULTA, true);
state.setSignal(ComputerSignal.EA, true);
//P -> P+1
state.setSignal(ComputerSignal.INCP, true);
state.sendSignals();
}
catch(IndexOutOfBoundsException exception)
{
throw new Exception("MUL");
}
break;
case MULI:
try{
state.setA(state.getA() *
memoryMap[ getIndirectAddress( ins.getInstructionOperator()
) ].getDataSigned());
state.setT(memoryMap[ getIndirectAddress( ins.getInstructionOperator() ) ].getDataSigned());
state.setI(getIndirectAddress( ins.getInstructionOperator() ));
state.setS(getIndirectAddress( ins.getInstructionOperator() ));
state.incrementP();
//Ahora señalamos qué registros han cambiado
state.setRegisterChanged(ComputerRegister.A, true);
state.setRegisterChanged(ComputerRegister.T, true);
state.setRegisterChanged(ComputerRegister.I, true);
state.setRegisterChanged(ComputerRegister.S, true);
state.setRegisterChanged(ComputerRegister.P, true);
//Aquí mostramos las señales usadas en el transcurso de la ejecución de la
instrucción.
//Algunos setSignal los comento, pero solo para no repetir llamadas iguales
//M(P) -> I
state.setSignal(ComputerSignal.SP, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
197
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);
//M(M(D)) ->A
state.setSignal(ComputerSignal.SD, true);
//state.setSignal(ComputerSignal.ES, true);
//state.setSignal(ComputerSignal.LECM, true);
//state.setSignal(ComputerSignal.ST, true);
//state.setSignal(ComputerSignal.EI, true);
//state.setSignal(ComputerSignal.SD, true);
//state.setSignal(ComputerSignal.ES, true);
//state.setSignal(ComputerSignal.LECM, true);
//state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EO, true);
state.setSignal(ComputerSignal.MULTA, true);
state.setSignal(ComputerSignal.EA, true);
//P -> P+1
state.setSignal(ComputerSignal.INCP, true);
state.sendSignals();
case DIV:
}
catch(IndexOutOfBoundsException exception)
{
throw new Exception("MULI");
}
break;
try{
state.setA(state.getA() /
memoryMap[ins.getInstructionOperator()].getDataSigned());
state.setT(memoryMap[ins.getInstructionOperator()].getDataSigned());
state.setI(ins.getDataSigned());
state.setS(ins.getInstructionOperator());
state.incrementP();
//Ahora señalamos qué registros han cambiado
state.setRegisterChanged(ComputerRegister.A, true);
state.setRegisterChanged(ComputerRegister.T, true);
state.setRegisterChanged(ComputerRegister.I, true);
state.setRegisterChanged(ComputerRegister.S, true);
state.setRegisterChanged(ComputerRegister.P, true);
//Aquí mostramos las señales usadas en el transcurso de la ejecución de la
instrucción.
//Algunos setSignal los comento, pero solo para no repetir llamadas iguales
//M(P) -> I
state.setSignal(ComputerSignal.SP, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);
//A+M(D) ->A
state.setSignal(ComputerSignal.SD, true);
//state.setSignal(ComputerSignal.ES, true);
//state.setSignal(ComputerSignal.LECM, true);
//state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EO, true);
state.setSignal(ComputerSignal.DIVA, true);
state.setSignal(ComputerSignal.EA, true);
//P -> P+1
state.setSignal(ComputerSignal.INCP, true);
state.sendSignals();
}
catch(IndexOutOfBoundsException exception)
{
throw new Exception("DIV");
}
break;
case DIVI:
try{
state.setA(state.getA() /
memoryMap[ getIndirectAddress( ins.getInstructionOperator()
) ].getDataSigned());
state.setT(memoryMap[ getIndirectAddress( ins.getInstructionOperator() ) ].getDataSigned());
state.setI(getIndirectAddress( ins.getInstructionOperator() ));
state.setS(getIndirectAddress( ins.getInstructionOperator() ));
state.incrementP();
//Ahora señalamos qué registros han cambiado
state.setRegisterChanged(ComputerRegister.A, true);
state.setRegisterChanged(ComputerRegister.T, true);
state.setRegisterChanged(ComputerRegister.I, true);
state.setRegisterChanged(ComputerRegister.S, true);
state.setRegisterChanged(ComputerRegister.P, true);
//Aquí mostramos las señales usadas en el transcurso de la ejecución de la
198
instrucción.
//Algunos setSignal los comento, pero solo para no repetir llamadas iguales
//M(P) -> I
state.setSignal(ComputerSignal.SP, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);
//M(M(D)) ->A
state.setSignal(ComputerSignal.SD, true);
//state.setSignal(ComputerSignal.ES, true);
//state.setSignal(ComputerSignal.LECM, true);
//state.setSignal(ComputerSignal.ST, true);
//state.setSignal(ComputerSignal.EI, true);
//state.setSignal(ComputerSignal.SD, true);
//state.setSignal(ComputerSignal.ES, true);
//state.setSignal(ComputerSignal.LECM, true);
//state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EO, true);
state.setSignal(ComputerSignal.DIVA, true);
state.setSignal(ComputerSignal.EA, true);
//P -> P+1
state.setSignal(ComputerSignal.INCP, true);
state.sendSignals();
case MOD:
}
catch(IndexOutOfBoundsException exception)
{
throw new Exception("DIVI");
}
break;
try{
state.setA(state.getA() %
memoryMap[ins.getInstructionOperator()].getDataSigned());
state.setT(memoryMap[ins.getInstructionOperator()].getDataSigned());
state.setI(ins.getDataSigned());
state.setS(ins.getInstructionOperator());
state.incrementP();
//Ahora señalamos qué registros han cambiado
state.setRegisterChanged(ComputerRegister.A, true);
state.setRegisterChanged(ComputerRegister.T, true);
state.setRegisterChanged(ComputerRegister.I, true);
state.setRegisterChanged(ComputerRegister.S, true);
state.setRegisterChanged(ComputerRegister.P, true);
//Aquí mostramos las señales usadas en el transcurso de la ejecución de la
instrucción.
//Algunos setSignal los comento, pero solo para no repetir llamadas iguales
//M(P) -> I
state.setSignal(ComputerSignal.SP, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);
//A+M(D) ->A
state.setSignal(ComputerSignal.SD, true);
//state.setSignal(ComputerSignal.ES, true);
//state.setSignal(ComputerSignal.LECM, true);
//state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EO, true);
state.setSignal(ComputerSignal.MODA, true);
state.setSignal(ComputerSignal.EA, true);
//P -> P+1
state.setSignal(ComputerSignal.INCP, true);
state.sendSignals();
}
catch(IndexOutOfBoundsException exception)
{
throw new Exception("MOD");
}
break;
case MODI:
try{
state.setA(state.getA() %
memoryMap[ getIndirectAddress( ins.getInstructionOperator()
) ].getDataSigned());
state.setT(memoryMap[ getIndirectAddress( ins.getInstructionOperator() ) ].getDataSigned());
state.setI(getIndirectAddress( ins.getInstructionOperator() ));
state.setS(getIndirectAddress( ins.getInstructionOperator() ));
state.incrementP();
//Ahora señalamos qué registros han cambiado
199
state.setRegisterChanged(ComputerRegister.A, true);
state.setRegisterChanged(ComputerRegister.T, true);
state.setRegisterChanged(ComputerRegister.I, true);
state.setRegisterChanged(ComputerRegister.S, true);
state.setRegisterChanged(ComputerRegister.P, true);
//Aquí mostramos las señales usadas en el transcurso de la ejecución de la
instrucción.
//Algunos setSignal los comento, pero solo para no repetir llamadas iguales
//M(P) -> I
state.setSignal(ComputerSignal.SP, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);
//M(M(D)) ->A
state.setSignal(ComputerSignal.SD, true);
//state.setSignal(ComputerSignal.ES, true);
//state.setSignal(ComputerSignal.LECM, true);
//state.setSignal(ComputerSignal.ST, true);
//state.setSignal(ComputerSignal.EI, true);
//state.setSignal(ComputerSignal.SD, true);
//state.setSignal(ComputerSignal.ES, true);
//state.setSignal(ComputerSignal.LECM, true);
//state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EO, true);
state.setSignal(ComputerSignal.MODA, true);
state.setSignal(ComputerSignal.EA, true);
//P -> P+1
state.setSignal(ComputerSignal.INCP, true);
state.sendSignals();
case SAL:
}
catch(IndexOutOfBoundsException exception)
{
throw new Exception("MODI");
}
break;
try{
state.setS(state.getP());
state.setT(ins.getDataSigned());
state.setI(ins.getDataSigned());
state.setP(ins.getInstructionOperator());
//Ahora señalamos qué registros han cambiado
state.setRegisterChanged(ComputerRegister.T, true);
state.setRegisterChanged(ComputerRegister.I, true);
state.setRegisterChanged(ComputerRegister.S, true);
state.setRegisterChanged(ComputerRegister.P, true);
//Aquí mostramos las señales usadas en el transcurso de la ejecución de la
instrucción.
//Algunos setSignal los comento, pero solo para no repetir llamadas iguales
//M(P) -> I
state.setSignal(ComputerSignal.SP, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);
//D -> P
state.setSignal(ComputerSignal.SD, true);
state.setSignal(ComputerSignal.EP, true);
state.sendSignals();
}
catch(IndexOutOfBoundsException exception)
{
throw new Exception("SAL");
}
break;
case SALI:
try{
state.setS(ins.getInstructionOperator());
state.setI(getIndirectAddress( ins.getInstructionOperator() ));
state.setT(getIndirectAddress( ins.getInstructionOperator() ));
state.setP( getIndirectAddress( ins.getInstructionOperator() ) );
//Ahora señalamos qué registros han cambiado
state.setRegisterChanged(ComputerRegister.T, true);
state.setRegisterChanged(ComputerRegister.I, true);
state.setRegisterChanged(ComputerRegister.S, true);
state.setRegisterChanged(ComputerRegister.P, true);
//Aquí mostramos las señales usadas en el transcurso de la ejecución de la
instrucción.
//Algunos setSignal los comento, pero solo para no repetir llamadas iguales
//M(P) -> I
state.setSignal(ComputerSignal.SP, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
200
state.setSignal(ComputerSignal.EI, true);
//M(D) -> P
state.setSignal(ComputerSignal.SD, true);
//state.setSignal(ComputerSignal.ES, true);
//state.setSignal(ComputerSignal.LECM, true);
//state.setSignal(ComputerSignal.ST, true);
//state.setSignal(ComputerSignal.EI, true);
//state.setSignal(ComputerSignal.SD, true);
state.setSignal(ComputerSignal.EP, true);
state.sendSignals();
case SAN:
}
catch(IndexOutOfBoundsException exception)
{
throw new Exception("SALI");
}
break;
try{
state.setS(state.getP());
state.setT(ins.getDataSigned());
state.setI(ins.getDataSigned());
if(state.getA() < 0)
{
state.setP(ins.getInstructionOperator());
//Ahora señalamos qué registros han cambiado
state.setRegisterChanged(ComputerRegister.T, true);
state.setRegisterChanged(ComputerRegister.I, true);
state.setRegisterChanged(ComputerRegister.S, true);
state.setRegisterChanged(ComputerRegister.P, true);
//Aquí mostramos las señales usadas en el transcurso de la ejecución
de la instrucción.
//Algunos setSignal los comento, pero solo para no repetir llamadas
iguales
//M(P) -> I
state.setSignal(ComputerSignal.SP, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);
//D -> P
state.setSignal(ComputerSignal.SD, true);
state.setSignal(ComputerSignal.EP, true);
state.sendSignals();
}
else
{
state.incrementP();
//Ahora señalamos qué registros han cambiado
state.setRegisterChanged(ComputerRegister.T, true);
state.setRegisterChanged(ComputerRegister.I, true);
state.setRegisterChanged(ComputerRegister.S, true);
state.setRegisterChanged(ComputerRegister.P, true);
//Aquí mostramos las señales usadas en el transcurso de la ejecución
de la instrucción.
//Algunos setSignal los comento, pero solo para no repetir llamadas
iguales
//M(P) -> I
state.setSignal(ComputerSignal.SP, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);
//P -> P+1
state.setSignal(ComputerSignal.INCP, true);
state.sendSignals();
}
}
catch(IndexOutOfBoundsException exception)
{
throw new Exception("SAN");
}
break;
case SANI:
try{
if(state.getA() < 0)
{
state.setS(ins.getInstructionOperator());
state.setI(getIndirectAddress( ins.getInstructionOperator() ));
state.setT(getIndirectAddress( ins.getInstructionOperator() ));
state.setP( getIndirectAddress( ins.getInstructionOperator() ) );
//Ahora señalamos qué registros han cambiado
state.setRegisterChanged(ComputerRegister.T, true);
state.setRegisterChanged(ComputerRegister.I, true);
state.setRegisterChanged(ComputerRegister.S, true);
201
state.setRegisterChanged(ComputerRegister.P, true);
//Aquí mostramos las señales usadas en el transcurso de la ejecución
de la instrucción.
//Algunos setSignal los comento, pero solo para no repetir llamadas
iguales
//M(P) -> I
state.setSignal(ComputerSignal.SP, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);
//M(D) -> P
state.setSignal(ComputerSignal.SD, true);
//state.setSignal(ComputerSignal.ES, true);
//state.setSignal(ComputerSignal.LECM, true);
//state.setSignal(ComputerSignal.ST, true);
//state.setSignal(ComputerSignal.EI, true);
//state.setSignal(ComputerSignal.SD, true);
state.setSignal(ComputerSignal.EP, true);
state.sendSignals();
}
else
{
state.setS(state.getP());
state.setT(ins.getDataSigned());
state.setI(ins.getDataSigned());
state.incrementP();
//Ahora señalamos qué registros han cambiado
state.setRegisterChanged(ComputerRegister.T, true);
state.setRegisterChanged(ComputerRegister.I, true);
state.setRegisterChanged(ComputerRegister.S, true);
state.setRegisterChanged(ComputerRegister.P, true);
//Aquí mostramos las señales usadas en el transcurso de la ejecución
de la instrucción.
//Algunos setSignal los comento, pero solo para no repetir llamadas
iguales
//M(P) -> I
state.setSignal(ComputerSignal.SP, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);
//P -> P+1
state.setSignal(ComputerSignal.INCP, true);
state.sendSignals();
case SAC:
}
}
catch(IndexOutOfBoundsException exception)
{
throw new Exception("SANI");
}
break;
try{
state.setS(state.getP());
state.setT(ins.getDataSigned());
state.setI(ins.getDataSigned());
//Ahora señalamos qué registros han cambiado
state.setRegisterChanged(ComputerRegister.T,
state.setRegisterChanged(ComputerRegister.I,
state.setRegisterChanged(ComputerRegister.S,
state.setRegisterChanged(ComputerRegister.P,
true);
true);
true);
true);
if(state.getA() == 0)
{
state.setP(ins.getInstructionOperator());
//Aquí mostramos las señales usadas en el transcurso de la ejecución
de la instrucción.
//Algunos setSignal los comento, pero solo para no repetir llamadas
iguales
//M(P) -> I
state.setSignal(ComputerSignal.SP, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);
//D -> P
state.setSignal(ComputerSignal.SD, true);
state.setSignal(ComputerSignal.EP, true);
state.sendSignals();
}
else
{
state.incrementP();
202
//Aquí mostramos las señales usadas en el transcurso de la ejecución
de la instrucción.
//Algunos setSignal los comento, pero solo para no repetir llamadas
iguales
//M(P) -> I
state.setSignal(ComputerSignal.SP, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);
//P -> P+1
state.setSignal(ComputerSignal.INCP, true);
state.sendSignals();
}
}
catch(IndexOutOfBoundsException exception)
{
throw new Exception("SAC");
}
break;
case SACI:
try{
//Ahora señalamos qué registros han cambiado
state.setRegisterChanged(ComputerRegister.T, true);
state.setRegisterChanged(ComputerRegister.I, true);
state.setRegisterChanged(ComputerRegister.S, true);
state.setRegisterChanged(ComputerRegister.P, true);
if(state.getA() == 0)
{
state.setS(ins.getInstructionOperator());
state.setI(getIndirectAddress( ins.getInstructionOperator() ));
state.setT(getIndirectAddress( ins.getInstructionOperator() ));
state.setP( getIndirectAddress( ins.getInstructionOperator() ) );
//Aquí mostramos las señales usadas en el transcurso de la ejecución
de la instrucción.
//Algunos setSignal los comento, pero solo para no repetir llamadas
iguales
//M(P) -> I
state.setSignal(ComputerSignal.SP, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);
//M(D) -> P
state.setSignal(ComputerSignal.SD, true);
//state.setSignal(ComputerSignal.ES, true);
//state.setSignal(ComputerSignal.LECM, true);
//state.setSignal(ComputerSignal.ST, true);
//state.setSignal(ComputerSignal.EI, true);
//state.setSignal(ComputerSignal.SD, true);
state.setSignal(ComputerSignal.EP, true);
state.sendSignals();
}
else
{
state.setS(state.getP());
state.setT(ins.getDataSigned());
state.setI(ins.getDataSigned());
state.incrementP();
//Aquí mostramos las señales usadas en el transcurso de la ejecución
de la instrucción.
//Algunos setSignal los comento, pero solo para no repetir llamadas
iguales
//M(P) -> I
state.setSignal(ComputerSignal.SP, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);
//P -> P+1
state.setSignal(ComputerSignal.INCP, true);
state.sendSignals();
case SAP:
}
}
catch(IndexOutOfBoundsException exception)
{
throw new Exception("SACI");
}
break;
try{
state.setS(state.getP());
state.setT(ins.getDataSigned());
state.setI(ins.getDataSigned());
203
//Ahora señalamos qué registros han cambiado
state.setRegisterChanged(ComputerRegister.T,
state.setRegisterChanged(ComputerRegister.I,
state.setRegisterChanged(ComputerRegister.S,
state.setRegisterChanged(ComputerRegister.P,
true);
true);
true);
true);
if(state.getA() > 0)
{
state.setP(ins.getInstructionOperator());
//Aquí mostramos las señales usadas en el transcurso de la ejecución
de la instrucción.
//Algunos setSignal los comento, pero solo para no repetir llamadas
iguales
//M(P) -> I
state.setSignal(ComputerSignal.SP, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);
//D -> P
state.setSignal(ComputerSignal.SD, true);
state.setSignal(ComputerSignal.EP, true);
state.sendSignals();
}
else
{
state.incrementP();
//Aquí mostramos las señales usadas en el transcurso de la ejecución
de la instrucción.
//Algunos setSignal los comento, pero solo para no repetir llamadas
iguales
//M(P) -> I
state.setSignal(ComputerSignal.SP, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);
//P -> P+1
state.setSignal(ComputerSignal.INCP, true);
state.sendSignals();
}
}
catch(IndexOutOfBoundsException exception)
{
throw new Exception("SAP");
}
break;
case SAPI:
try{
//Ahora señalamos qué registros han cambiado
state.setRegisterChanged(ComputerRegister.T, true);
state.setRegisterChanged(ComputerRegister.I, true);
state.setRegisterChanged(ComputerRegister.S, true);
state.setRegisterChanged(ComputerRegister.P, true);
if(state.getA() > 0)
{
state.setS(ins.getInstructionOperator());
state.setI(getIndirectAddress( ins.getInstructionOperator() ));
state.setT(getIndirectAddress( ins.getInstructionOperator() ));
state.setP( getIndirectAddress( ins.getInstructionOperator() ) );
//Aquí mostramos las señales usadas en el transcurso de la ejecución
de la instrucción.
//Algunos setSignal los comento, pero solo para no repetir llamadas
iguales
//M(P) -> I
state.setSignal(ComputerSignal.SP, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);
//M(D) -> P
state.setSignal(ComputerSignal.SD, true);
//state.setSignal(ComputerSignal.ES, true);
//state.setSignal(ComputerSignal.LECM, true);
//state.setSignal(ComputerSignal.ST, true);
//state.setSignal(ComputerSignal.EI, true);
//state.setSignal(ComputerSignal.SD, true);
state.setSignal(ComputerSignal.EP, true);
state.sendSignals();
}
else
{
state.setS(state.getP());
state.setT(ins.getDataSigned());
204
state.setI(ins.getDataSigned());
state.incrementP();
//Aquí mostramos las señales usadas en el transcurso de la ejecución
de la instrucción.
//Algunos setSignal los comento, pero solo para no repetir llamadas
iguales
//M(P) -> I
state.setSignal(ComputerSignal.SP, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);
//P -> P+1
state.setSignal(ComputerSignal.INCP, true);
state.sendSignals();
case ECA:
}
}
catch(IndexOutOfBoundsException exception)
{
throw new Exception("SAPI");
}
break;
try{
state.setE(memoryMap[ins.getInstructionOperator()].getDataSigned());
state.setT(state.getE());
state.setI(ins.getDataSigned());
state.setS(ins.getInstructionOperator());
state.getListener().writeCharacterToScreen();
state.incrementP();
//Ahora señalamos qué registros han cambiado
state.setRegisterChanged(ComputerRegister.E, true);
state.setRegisterChanged(ComputerRegister.T, true);
state.setRegisterChanged(ComputerRegister.I, true);
state.setRegisterChanged(ComputerRegister.S, true);
state.setRegisterChanged(ComputerRegister.P, true);
//Aquí mostramos las señales usadas en el transcurso de la ejecución de la
instrucción.
//Algunos setSignal los comento, pero solo para no repetir llamadas iguales
//M(P) -> I
state.setSignal(ComputerSignal.SP, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);
//M(D) ->E
state.setSignal(ComputerSignal.SD, true);
//state.setSignal(ComputerSignal.ES, true);
//state.setSignal(ComputerSignal.LECM, true);
//state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EE, true);
state.setSignal(ComputerSignal.ESCP, true);
//P -> P+1
state.setSignal(ComputerSignal.INCP, true);
state.sendSignals();
}
catch(IndexOutOfBoundsException exception)
{
throw new Exception("ECA");
}
break;
case ECAI:
try{
state.setE(memoryMap[ getIndirectAddress( ins.getInstructionOperator() ) ].getDataSigned());
state.setT(state.getE());
state.setI(getIndirectAddress( ins.getInstructionOperator() ));
state.setS(getIndirectAddress( ins.getInstructionOperator() ));
state.getListener().writeCharacterToScreen();
state.incrementP();
//Ahora señalamos qué registros han cambiado
state.setRegisterChanged(ComputerRegister.E, true);
state.setRegisterChanged(ComputerRegister.T, true);
state.setRegisterChanged(ComputerRegister.I, true);
state.setRegisterChanged(ComputerRegister.S, true);
state.setRegisterChanged(ComputerRegister.P, true);
//Aquí mostramos las señales usadas en el transcurso de la ejecución de la
instrucción.
//Algunos setSignal los comento, pero solo para no repetir llamadas iguales
//M(P) -> I
state.setSignal(ComputerSignal.SP, true);
205
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);
//M(M(D)) ->A
state.setSignal(ComputerSignal.SD, true);
//state.setSignal(ComputerSignal.ES, true);
//state.setSignal(ComputerSignal.LECM, true);
//state.setSignal(ComputerSignal.ST, true);
//state.setSignal(ComputerSignal.EI, true);
//state.setSignal(ComputerSignal.SD, true);
//state.setSignal(ComputerSignal.ES, true);
//state.setSignal(ComputerSignal.LECM, true);
//state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EE, true);
state.setSignal(ComputerSignal.ESCP, true);
//P -> P+1
state.setSignal(ComputerSignal.INCP, true);
state.sendSignals();
case LCA:
}
catch(IndexOutOfBoundsException exception)
{
throw new Exception("ECAI");
}
break;
try{
/**
* Before executing this instruction,
* the input from the keyboard should have been saved into register E.
*/
int operator = ins.getInstructionOperator();
memoryMap[operator].setInstructionSigned(state.getE());
state.setT(state.getE());
state.setI(ins.getDataSigned());
state.setS(operator);
state.getListener().memoryChanged(memoryMap[operator]);
state.setChangedMemory(memoryMap[operator].getAddressLocation());
state.incrementP();
//Ahora señalamos qué registros han cambiado
state.setRegisterChanged(ComputerRegister.T, true);
state.setRegisterChanged(ComputerRegister.I, true);
state.setRegisterChanged(ComputerRegister.S, true);
state.setRegisterChanged(ComputerRegister.P, true);
//Aquí mostramos las señales usadas en el transcurso de la ejecución de la
instrucción.
//Algunos setSignal los comento, pero solo para no repetir llamadas iguales
//M(P) -> I
state.setSignal(ComputerSignal.SP, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);
//E -> M(D)
state.setSignal(ComputerSignal.SD, true);
//state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LEET, true);
state.setSignal(ComputerSignal.SE, true);
state.setSignal(ComputerSignal.ET, true);
state.setSignal(ComputerSignal.ESCM, true);
//P -> P+1
state.setSignal(ComputerSignal.INCP, true);
state.sendSignals();
}
catch(IndexOutOfBoundsException exception)
{
throw new Exception("LCA");
}
break;
case LCAI:
try{
/**
* Before executing this instruction,
* the input from the keyboard should have been saved into register E.
*/
int operator = getIndirectAddress( ins.getInstructionOperator() );
memoryMap[operator].setInstructionSigned(state.getE());
state.setT(state.getE());
state.setI(operator);
state.setS(operator);
206
state.getListener().memoryChanged(memoryMap[operator]);
state.setChangedMemory(memoryMap[operator].getAddressLocation());
state.incrementP();
//Ahora señalamos qué registros han cambiado
state.setRegisterChanged(ComputerRegister.T, true);
state.setRegisterChanged(ComputerRegister.I, true);
state.setRegisterChanged(ComputerRegister.S, true);
state.setRegisterChanged(ComputerRegister.P, true);
//Aquí mostramos las señales usadas en el transcurso de la ejecución de la
instrucción.
//Algunos setSignal los comento, pero solo para no repetir llamadas iguales
//M(P) -> I
state.setSignal(ComputerSignal.SP, true);
state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LECM, true);
state.setSignal(ComputerSignal.ST, true);
state.setSignal(ComputerSignal.EI, true);
//A -> M(M(D))
state.setSignal(ComputerSignal.SD, true);
//state.setSignal(ComputerSignal.ES, true);
//state.setSignal(ComputerSignal.LECM, true);
//state.setSignal(ComputerSignal.ST, true);
//state.setSignal(ComputerSignal.EI, true);
//state.setSignal(ComputerSignal.SD, true);
//state.setSignal(ComputerSignal.ES, true);
state.setSignal(ComputerSignal.LEET, true);
state.setSignal(ComputerSignal.SE, true);
state.setSignal(ComputerSignal.ET, true);
state.setSignal(ComputerSignal.ESCM, true);
//P -> P+1
state.setSignal(ComputerSignal.INCP, true);
state.sendSignals();
}
catch(IndexOutOfBoundsException exception)
{
throw new Exception("LCAI");
}
break;
}
}
else
{
throw new Exception("The emulator arrived to a memory address with no instruction. The memory map
may have not ben properly initialized");
}
}
//Ya hemos ejecutado la instrucción así que apagamos el semáforo.
trafficLight = false;
return getState();
}
}
207
11.1.15 Instruction.java
package xenon;
/**
*
* @brief Clase que contiene una instrucción
*
*/
public class Instruction {
//Constantes útiles
public static final int Memory_Address_Limit = 2047;
public static final int Instruction_Size_Limit = 65535;
public static final int Register_Max_Limit = 32767;
public static final int Register_Min_Limit = -32768;
public static final int Operation_Code_Max = 31;
/**
*
* @brief Códigos de operación.
*
*/
public enum OperationCode {
ALT(0, 0), ALM(1, 2), ALMI(2, 3), CAR(3, 4), CARI(4, 5), ESC(5, 6),
ESCI(6, 7), LEE(7, 8), LEEI(8, 9), SUM(9, 10), SUMI(10, 11), RES(11, 12),
RESI(12, 13), MUL(13, 14), MULI(14, 15), DIV(15, 16), DIVI(16, 17), MOD(17,
MODI(18, 19), SAL(19, 20), SALI(20, 21), SAN(21, 22), SANI(22, 23), SAC(23,
SACI(24, 25), SAP(25, 26), SAPI(26, 27), ECA(27, 28), ECAI(28, 29),
LCA(29, 30), LCAI(30, 31);
18),
24),
private int index;
//Código de operación, en base 10
private int code;
OperationCode(int i, int c)
{
index = i;
code = c;
}
public int index()
{
return index;
}
public int code()
{
return code;
}
public boolean addressingMode()
{
return ((code & 0x01) == 1)? true : false;
}
};
//Una instrucción es un código de operación + operador (una dirección de memoria)
private OperationCode operationCode;
private int insOperator; //Operador de la instrucción (normalmente será una dirección de memoria)
private int data; //sin signo 16 bit, [0, 65535]. Los números negativos se guardarán en complemento a 2 de 16bit
private boolean isInstruction;
private int addressLocation;
/**
* @brief Constructor.
*/
Instruction()
{
data = 0;
isInstruction = false;
insOperator = -1;
addressLocation = -1;
}
/**
* @detail Constructor que inicializa el contenido de la instrucción (código+operador),
* pero no define la posición de memoria en que se encuentra la instrucción.
* @param oc Código de operación
* @param operator operador
*/
Instruction(OperationCode oc, int operator)
{
addressLocation = -1;
data = 0;
isInstruction = false;
insOperator = -1;
setInstruction(oc, operator);
}
/**
* @detail Método que inicializa el contenido de la instrucción (código+operador),
* pero no define la posición de memoria en que se encuentra la instrucción.
* @param oc Código de operación
* @param operator operador
*/
public int setInstruction(OperationCode oc, int operator)//TODO: throws Exception
{
208
int r = 0;
operationCode = oc;
if(operator <= Memory_Address_Limit && operator >= 0)
{
if(oc != null)
{
isInstruction = true;
insOperator = operator;
}
else
{
isInstruction = false;
r = -2;
}
}
else
{
isInstruction = false;
r = -1;
}
updateFromInstruction();
return r;
}
/**
* @detail Sitúa la instrucción en la posición de memoria 'ma'.
* @param ma posición de memoria de la instrucción
* @return
* @throws Exception Será lanzada si la posición de memoria está fuera de rango
*/
public int setAddressLocation(int ma) throws Exception
{
int r = -1;
if(ma <= Memory_Address_Limit && ma >= 0)
{
addressLocation = ma;
r = 0;
}
else
{
throw new Exception("Error: Dirección " + ma + " fuera de rango");
}
return r;
}
/**
* @brief Devuelve la posición de memoria de la instrucción
* @return Posición de memoria de la instrucción
*/
public int getAddressLocation()
{
return addressLocation;
}
public boolean isInstruction()
{
return isInstruction;
}
/**
* Método que cambia el código de operación de la instrucción
* @param oc
* @return
* TODO: Eliminar return parametro
*/
public int setOperationCode(OperationCode oc)
{
operationCode = oc;
int r = 0;
if(insOperator <= Memory_Address_Limit && insOperator >= 0)
{
if(operationCode != null)
{
isInstruction = true;
}
else
{
isInstruction = false;
r = -2;
}
}
else
{
isInstruction = false;
r = -1;
}
updateFromInstruction();
return r;
}
/**
* Método que cambia el operador de la instrucción
* @param operator
* @return
209
*/
public int setInstructionOperator(int operator)
{
int r = 0;
if(operator <= Memory_Address_Limit && operator >= 0)
{
if(operationCode != null)
{
isInstruction = true;
}
else
{
isInstruction = false;
r = -2;
}
insOperator = operator;
updateFromInstruction();
}
else
{
isInstruction = false;
r = -1;
}
return r;
}
/**
* @brief Toma como entrada el dato (con signo) que corresponde a la instrucción.
* El parámetro d debe pertenecer a [-32768, 32767] o lanzará una excepción
*/
public void setInstructionSigned(int d) throws Exception
{
if(d >= -(Instruction_Size_Limit+1)/2 && d <= (Instruction_Size_Limit+1)/2 -1)
{
if(d >= 0)
{
data = d;
}
else
{
//Pasamos de número negativo a complemento a 2 (16bit).
data = d+(Instruction_Size_Limit+1);
}
updateFromData();
}
else
{
throw new Exception("The number " + d + " cannot be an instruction");
}
}
/**
* @brief Toma como entrada el dato (sin signo) que corresponde a la instrucción.
* El parámetro d debe pertenecer a [0, 65535] o lanzará una excepción.
*/
public void setInstructionUnsigned(int d) throws Exception
{
if(d >= 0 && d <= Instruction_Size_Limit)
{
data = d;
updateFromData();
}
else
{
throw new Exception("The number " + d + " cannot be an instruction");
}
}
/**
* Devuelve el código de operación de la instrucción.
* @return Código de operación
*/
public OperationCode getOperationCode()
{
return operationCode;
}
/**
* Devuelve el operador de la instrucción
* @return Operador de la instrucción
*/
public int getInstructionOperator()
{
return insOperator;
}
/**
* Devuelve el dato guardado en memoria, sin signo
* @return
*/
210
public int getDataUnsigned()
{
return data;
}
/**
* Devuelve el dato guardado en memoria, con signo
* @return
*/
public int getDataSigned()
{
int r = 0;
int conditional = (((Instruction_Size_Limit+1)/2)-1);
if(data <= conditional)
{
r = data;
}
else
{
//Pasamos de complemento a 2 a número con signo
r = data-(Instruction_Size_Limit+1);
}
return r;
}
/**
* @brief Calcula qué código de operación y operador tiene la instrucción a partir del dato guardado en memoria
*/
private void updateFromData()
{
//int oc = (data & 0xF000) >> 12;
int code = (data & 0xF800) >> 11;
//if( oc >= 0 && oc <= Operation_Code_Max )
if( code >= 0 && code <= Operation_Code_Max )
{
int i = -1;
for(OperationCode getIndex: OperationCode.values())
{
if(code == getIndex.code())
{
i = getIndex.index();
break;
}
}
if(i != -1)
{
operationCode = OperationCode.values()[i];
insOperator = (data & 0x07FF);
isInstruction = true;
}
else
{
isInstruction = false;
}
}
else
{
isInstruction = false;
}
}
/**
* Calcula el dato a guardar en memoria
*/
private void updateFromInstruction()
{
int foo = 0;
if(isInstruction())
{
foo = (operationCode.code() << 11) | insOperator;
}
else
{
if(operationCode == null && insOperator != -1)
{
foo = insOperator;
}
else if (operationCode != null&& insOperator == -1)
{
foo = operationCode.code() << 11;
}
}
try{
setInstructionUnsigned(foo);
}
catch(Exception e)
{
//TODO:
}
}
/**
211
* @brief Crea una cadena que representa la instrucción.
*/
public String toString()
{
String s = null;
if(isInstruction())
{
if(operationCode == OperationCode.ALT)
{
s = Integer.toString(addressLocation,16)+ ": " + operationCode.name()
+ " : " + Integer.toString(getDataSigned(), 16);
}
else
{
s = Integer.toString(addressLocation,16)+ ": " + operationCode.name()
+ " " + Integer.toString(insOperator, 16) + " : " +
Integer.toString(getDataSigned(), 16);
}
}
else
{
s = Integer.toString(addressLocation,16)+ ": " + Integer.toString(getDataSigned(), 16);
}
return s;
}
}
212
11.1.16 ProjectsManager.java
package xenon;
import
import
import
import
import
java.awt.event.MouseEvent;
java.awt.event.MouseListener;
java.io.File;
java.io.FilenameFilter;
java.util.ArrayList;
import
import
import
import
import
import
import
javax.swing.JFileChooser;
javax.swing.JOptionPane;
javax.swing.JTree;
javax.swing.tree.DefaultMutableTreeNode;
javax.swing.tree.DefaultTreeModel;
javax.swing.tree.TreePath;
javax.swing.tree.TreeSelectionModel;
/**
*
* @brief Clase gestora de los proyectos abiertos
*
*/
public class ProjectsManager implements MouseListener {
ArrayList<Project> projectsList; //Lista de proyectos
Project currentlySelectedProject;//Proyecto que se encuentra seleccionado actualmente
ProjectFile currentlySelectedFileInJTree; //Fichero seleccionado en el árbol de ficheros
JTree projectsTree; //Árbol de ficheros
TabsManager tabsManager; //Gestor de pestañas
public ProjectsManager(TabsManager tm)
{
//Inicializamos variables
currentlySelectedFileInJTree = null;
projectsList = new ArrayList<Project>();
DefaultMutableTreeNode top = new DefaultMutableTreeNode("Proyectos");
projectsTree = new JTree(top);
projectsTree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
projectsTree.addMouseListener(this);
tabsManager = tm;
currentlySelectedProject = null;
}
public JTree getProjectsTree()
{
return projectsTree;
}
public Project getCurrentlySelectedProject()
{
return currentlySelectedProject;
}
public ProjectFile getCurrentlySelectedFileInJTree()
{
return currentlySelectedFileInJTree;
}
public void closeProject()
{
boolean b = true;
if(currentlySelectedProject != null)
{
//Cerramos pestañas
b = tabsManager.closeAllTabsOfProject(currentlySelectedProject);
//Si todo fue bien eliminamos los nodos del proyecto del árbol de proyectos
if (b == true)
{
DefaultTreeModel model = (DefaultTreeModel) projectsTree.getModel();
model.removeNodeFromParent(currentlySelectedProject.pnode);
projectsTree.setModel(model);
projectsList.remove(currentlySelectedProject);
}
}
}
/**
* @brief Elimina un fichero del árbol de proyectos
* @param pf
*/
public void removeFileFromJTree(ProjectFile pf)
{
TreePath tp = new TreePath(pf.project.pnode.getPath());
DefaultMutableTreeNode root = (DefaultMutableTreeNode)projectsTree.getModel().getRoot();
DefaultTreeModel tm = new DefaultTreeModel(root);
pf.project.projectFiles.remove(pf);
pf.project.pnode.remove(pf.fnode);
213
projectsTree.setModel(tm);
projectsTree.expandPath(tp);
}
/**
*
* @param pf
* @return
*/
public File addBinaryFromCode(ProjectFile pf)
{
String arg1 = pf.file.getPath();
int lastIndex = arg1.lastIndexOf('.');
String str = arg1.substring(0, lastIndex) + ".ece";
File filep = new File(str);
//Si el fichero ya existe en el árbol, no necesitamos añadirlo
boolean flag = true;
for(ProjectFile p : pf.project.projectFiles)
{
if( filep.getAbsolutePath().equals( p.file.getAbsolutePath() ) )
{
flag = false;
filep = p.file;
}
}
//Si flag == true, el fichero todavía no existe en el árbol de proyectos, luego lo añadimos
if(flag == true)
{
DefaultMutableTreeNode root = (DefaultMutableTreeNode)projectsTree.getModel().getRoot();
//Creamos un nuevo ProjectFile
ProjectFile prfile = new ProjectFile(filep, pf.project);
//Añadimos dicho ProjectFile a la lista de ficheros del proyecto
pf.project.projectFiles.add(prfile);
//Creamos un TreeNode para dicho ProjectFile
DefaultMutableTreeNode node = new DefaultMutableTreeNode(prfile);
prfile.setNode(node);
//Añadimos dicho nodo a la lista de nodos del proyecto
pf.project.pnode.add(node);
//Actualizamos el modelo del árbol de proyectos
DefaultTreeModel tm = new DefaultTreeModel(root);
projectsTree.setModel(tm);
//Seleccionamos el nodo perteneciente al fichero añadido en el árbol de proyectos
projectsTree.expandPath(new TreePath(pf.project.pnode.getPath()));
//System.out.println("Añadido fichero " + filep.getName() + " al proyecto " + pf.project.file.getName()
//
+ " " + pf.project.pnode.isNodeChild(node));
}
return filep;
}
/**
* @brief Crea un nuevo proyecto.
*/
public void createProject()
{
JFileChooser fc = new JFileChooser();
fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
int returnVal = fc.showDialog(null, "Nuevo Proyecto");
if (returnVal == JFileChooser.APPROVE_OPTION) {
File projectDir = fc.getSelectedFile();
if(projectDir.exists())
{
JOptionPane.showMessageDialog(null,
"El proyecto no ha podido ser creado en el directorio elegido " +
"porque dicho directorio ya existe.");
}
else
{
//Creamos un nuevo directorio
boolean success = projectDir.mkdir();
if(success)
{
//Creamos un fichero ls2 con el nombre del proyecto
File f = new File(projectDir.getAbsolutePath() + "/" + projectDir.getName() + ".ls2");
try{
f.createNewFile();
}
catch(Exception y)
{
}
//Abrimos el proyecto
openProject(projectDir);
}
214
else
{
JOptionPane.showMessageDialog(null,
"Ha ocurrido un error al crear el directorio del proyecto.");
}
}
System.out.println("Creando proyecto en: " + projectDir.getPath() + ".");
} else {
System.out.println("Comando de crear proyecto cancelado por el usuario.");
}
}
/**
* @brief Abre el proyecto que está en el directorio que contiene el parámetro file
* @param file
*/
private void openProject(File file)
{
//Comprobamos si dicho proyecto ya está abierto
boolean flag = true;
for(Project p : projectsList)
{
if( file.getPath().equals( p.file.getPath() ) )
{
flag = false;
}
}
//Si flag == true, el proyecto todavía no se ha abierto
if (flag == true)
{
System.out.println("Abriendo: " + file.getAbsolutePath() + ".");
//Creamos un filtro de forma que solo obtengamos ficheros con las extensiones txt, ls2 o ece
FilenameFilter filter = new FilenameFilter(){
@Override
public boolean accept(File arg0, String name) {
String arg1 = name.toLowerCase();
if(arg1.lastIndexOf('.')>0)
{
// get last index for '.' char
int lastIndex = arg1.lastIndexOf('.');
// get extension
String str = arg1.substring(lastIndex);
// match path name extension
if(str.equals(".txt") || str.equals(".ls2") || str.equals(".ece"))
{
return true;
}
}
return false;
}
};
//Obtenemos la lista de ficheros del proyecto aplicando el filtro.
File[] fileList = file.listFiles(filter);
Project p = new Project();
p.file = file;
DefaultMutableTreeNode root = (DefaultMutableTreeNode)projectsTree.getModel().getRoot();
//Nodo del proyecto en el árbol de proyectos
DefaultMutableTreeNode project = new DefaultMutableTreeNode(p);
p.pnode = project;
DefaultMutableTreeNode node;
for(File filep:fileList)
{
if(filep.exists())
{
//Añadimos el fichero al proyecto
ProjectFile prfile = new ProjectFile(filep, p);
p.projectFiles.add(prfile);
node = new DefaultMutableTreeNode(prfile);
prfile.setNode(node);
project.add(node);
//tabsManager.addTab(prfile);
}
}
//Añadir proyecto a la lista de proyectos
root.add(project);
//Actualizar el modelo del árbol de proyectos con los nuevos nodos
DefaultTreeModel tm = new DefaultTreeModel(root);
projectsTree.setModel(tm);
//Seleccionar el proyecto que acabamos de abrir
215
projectsTree.expandPath(new TreePath(project.getPath()));
projectsList.add(p);
}
}
/**
* @brief Muestra una ventana para seleccionar el proyecto que queremos abrir, y luego abre dicho proyecto
*/
public void openProject()
{
JFileChooser fc = new JFileChooser();
fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
int returnVal = fc.showDialog(null, "Abrir Proyecto");
if (returnVal == JFileChooser.APPROVE_OPTION) {
File file = fc.getSelectedFile();
openProject(file);
} else {
System.out.println("Comando de apertura cancelado por el usuario.");
}
}
@Override
public void mouseClicked(MouseEvent arg0) {
}
@Override
public void mouseEntered(MouseEvent arg0) {
}
@Override
public void mouseExited(MouseEvent arg0) {
}
/**
* @detail Un click selecciona el fichero/proyecto. Dos clicks abre el fichero en cuestión
*/
@Override
public void mousePressed(MouseEvent e) {
int selRow = projectsTree.getRowForLocation(e.getX(), e.getY());
TreePath selPath = projectsTree.getPathForLocation(e.getX(), e.getY());
if(selRow != -1) {
if(e.getClickCount() == 2) //doble click, abrir fichero seleccionado
{
DefaultMutableTreeNode node = (DefaultMutableTreeNode)selPath.getLastPathComponent();
if(selPath.getPathCount() == 3 && node.isLeaf())
{
ProjectFile pf = (ProjectFile)node.getUserObject();
//System.out.println(selPath.getPathCount() + " " + selPath + " " + pf.file.getPath());
//Añadir pestaña, o, si ya existía, seleccionarla y mostrar el archivo
tabsManager.addTab(pf);
}
}
else if(e.getClickCount() == 1) //un click, actualizamos el fichero y proyecto seleccionados
{
DefaultMutableTreeNode l = (DefaultMutableTreeNode)selPath.getLastPathComponent();
if(selPath.getPathCount() >= 2)
{
DefaultMutableTreeNode node = (DefaultMutableTreeNode)selPath.getPathComponent(1);
currentlySelectedProject = (Project)node.getUserObject();
//System.out.println(currentlySelectedProject);
}
if(selPath.getPathCount() == 3 && l.isLeaf())
{
currentlySelectedFileInJTree = (ProjectFile)l.getUserObject();
}
else
{
currentlySelectedFileInJTree = null;
}
}
}
}
@Override
public void mouseReleased(MouseEvent arg0) {
}
}
216
11.1.17 XenonHelper.java
package xenon;
import
import
import
import
import
import
java.io.File;
java.io.FileInputStream;
java.io.FileNotFoundException;
java.io.FileOutputStream;
java.io.IOException;
java.util.ArrayList;
/**
*
* @brief Clase que realiza tareas de compilación y lectura de binarios.
*
*/
public class XenonHelper {
/**
*
* @brief Lista de pseudoinstrucciones
*
*/
public enum PseudoInstruction { ORG, ESP, CTE, FIN, DRE };
/*
* Este método recoge la salida del método translateToInstructions(String) y lo convierte
* en un mapa de memoria
*/
public static ArrayList<Instruction> generateMemoryMap(ArrayList<Instruction> in)
{
int n = 0;
//Primero localizamos la dirección de memoria más alta con alguna instrucción.
for(Instruction i: in)
{
int m = i.getAddressLocation();
if(m > n)
{
n = m;
}
}
ArrayList<Instruction> map = new ArrayList<Instruction>(n+1);
int d = 0;
//Rellenamos el mapa de memoria con instrucciones en blanco
for(int i = 0; i <= n; i++)
{
Instruction e = new Instruction();
try{
e.setAddressLocation(i);
e.setInstructionSigned(d);
}
catch(Exception x){
//TODO
}
map.add(e);
}
//Reemplazamos las instrucciones en blanco con las reales
for(Instruction i: in)
{
map.set(i.getAddressLocation(), i);
}
return map;
}
/**
* @brief Lee una cadena de texto y la traduce a instrucciones
* @param code
* @return
*/
@SuppressWarnings("unused")
public static ArrayList<Instruction> translateToInstructions(String code) throws Exception
{
ArrayList<Instruction> array = new ArrayList<Instruction>();
ArrayList<LineCode> lineCodeArray = new ArrayList<LineCode>();
String[] lines = code.split(System.getProperty("line.separator"));
int lineCounter = 0;
boolean arrivedToFIN = false;
for(String line: lines)
{
if(arrivedToFIN == false)
{
lineCounter++;
boolean thereIsSomething = false;
LineCode l = new LineCode();
//String[] words = line.split(" ");
String[] words = line.split("\\s+");
217
ArrayList<String> awords
= new ArrayList<String>();
String mensaje = new String("");
for(String w: words)
{
if(w.indexOf(" ") == -1 && w.length() > 0)
{
awords.add(new String(w));
}
}
words = awords.toArray(new String[awords.size()]);
for(String w: words)
{
mensaje += " | " + w ;
}
//System.out.println("Línea " + lineCounter + " : " + mensaje);
int index = 0;
if(words.length > 0)
{
if(words[index].lastIndexOf(":") == words[index].length()-1 && words[index].length() >
1)
{
l.label = words[index].substring(0, words[0].length()-1);
index++;
}
}
if(words.length > index)
{
try{
l.instruction.setOperationCode(Instruction.OperationCode.valueOf(words[index]));
index++;
if(words.length == index + 1)
{
//There is an address
thereIsSomething = true;
l.addressLabel = words[index];
}
else if(l.instruction.getOperationCode() == Instruction.OperationCode.ALT)
{
thereIsSomething = true;
l.addressLabel = "0";
}
else if(words.length == index )
{
throw new Exception("Error en línea " + lineCounter +
" : falta dirección de memoria en la instrucción:
" + line);
}
else if(words.length >= index + 2)
{
throw new Exception("Error en línea " + lineCounter +
" : la instrucción solo ha de tener un argumento:
" + line);
}
}
catch (IllegalArgumentException e)
{
try{
l.pseudoInstruction = PseudoInstruction.valueOf(words[index]);
}
catch(Exception excp)
{
throw new Exception("Error en línea " + lineCounter +
" : instrucción '" + words[index] + "' no
reconocida en: "+ line );
}
index++;
if(l.pseudoInstruction == PseudoInstruction.FIN)
{
if(words.length == index)
{
thereIsSomething = true;
arrivedToFIN = true;
}
else
{
throw new Exception("Error en línea " +
lineCounter +
" : La pseudoinstrucción FIN
no ha de tener argumentos: " + line);
}
//Salimos del bucle for
break;
}
else if(l.pseudoInstruction == PseudoInstruction.ORG)
{
if(words.length == index +1)
{
218
l.addressLabel = words[index];
thereIsSomething = true;
}
else if (words.length == index)
{
throw new Exception("Error en línea " +
lineCounter +
" : falta dirección de memoria
en la pseudoinstrucción: " + line);
}
else if (words.length >= index +2)
{
throw new Exception("Error en línea " +
lineCounter +
" : la pseudoinstrucción solo
ha de tener un argumento: " + line);
}
}
else if(l.pseudoInstruction == PseudoInstruction.ESP)
{
if(words.length == index +1)
{
l.addressLabel = words[index];
thereIsSomething = true;
}
else if (words.length >= index +2)
{
throw new Exception("Error en línea " +
lineCounter +
" : la pseudoinstrucción solo
ha de tener un argumento: " + line);
}
else if (words.length == index)
{
throw new Exception("Error en línea " +
lineCounter +
" : falta número de espacios
en la pseudoinstrucción: " + line);
}
}
else if(l.pseudoInstruction == PseudoInstruction.CTE)
{
if(words.length == index + 1)
{
//l.addressLabel = words[index];
int bar = -1;
try{
bar = Integer.parseInt(words[index]);
}
catch (Exception ex)
{
throw new Exception("Error en línea "
+ lineCounter +
" : la constante "+
words[index] +
" no es un número: " + line.toString());
}
if(bar < Instruction.Register_Min_Limit || bar >
Instruction.Register_Max_Limit)
{
throw new Exception("Error en línea "
+ lineCounter +
" : constante fuera
de rango en la pseudoinstrucción: " + line.toString());
}
else
{
l.instruction.setInstructionSigned(bar);
thereIsSomething = true;
}
}
else if (words.length == index)
{
throw new Exception("Error en línea " +
lineCounter +
" : falta definir la constante
en la pseudoinstrucción: " + line.toString());
}
else if (words.length >= index +2)
{
throw new Exception("Error en línea " +
lineCounter +
" : la pseudoinstrucción solo
ha de tener un argumento: " + line);
}
}
else if(l.pseudoInstruction == PseudoInstruction.DRE)
{
if(words.length == index +1)
{
l.addressLabel = words[index];
thereIsSomething = true;
}
219
else if (words.length == index)
{
throw new Exception("Error en línea " +
lineCounter +
" : falta etiqueta en la
instrucción: " + line);
}
else if (words.length >= index +2)
{
throw new Exception("Error en línea " +
lineCounter +
" : la pseudoinstrucción solo
ha de tener un argumento: " + line);
}
}
}
}
if(thereIsSomething)
{
l.lineNumber = lineCounter;
l.address = lineCodeArray.size();
lineCodeArray.add(l);
}
}
}
if(arrivedToFIN == false)
{
throw new Exception("Error de sintaxis: Falta la directiva FIN" );
}
//Hemos leído las lineas, pero no hemos interpretado dónde está cada línea dentro de la posición de memoria
int indexCounter = 0;
int lastORGContent = 0;
int lastORGIndex = 0;
int lastESPContent = 0;
/**
* TODO: La instrucción ESP 4 debría dejar 4 espacios (cada espacio es del tamaño de una instr, 2 bytes)
* en blanco.
*/
for(LineCode line: lineCodeArray)
{
if(line.pseudoInstruction == PseudoInstruction.ORG)
{
//El +1 es porque ORG es una pseudoinstrucción que no se encuentra en ninguna posición de memoria
lastORGIndex = indexCounter + 1;
try {
lastORGContent = Integer.parseInt(line.addressLabel);
line.instruction.setAddressLocation(lastORGContent);
line.address = line.instruction.getAddressLocation();
lastESPContent = 0;
}
catch (Exception e)
{
throw new Exception("Error en línea " + line.lineNumber +
" : '" + line.addressLabel + "' no es un número: " +
lines[line.lineNumber-1]);
}
}
else if(line.pseudoInstruction == PseudoInstruction.ESP)
{
int a =0;
line.address = lastORGContent + lastESPContent + indexCounter - lastORGIndex;
try {
a = Integer.parseInt(line.addressLabel)-1;
}
catch (Exception e)
{
throw new Exception("Error en línea " + line.lineNumber +
" : '" + a + "' no es un número: " + lines[line.lineNumber-1]);
}
if(a < 0)
{
throw new Exception("Error en línea " + line.lineNumber +
" : El argumento '" + (a+1) + "' es un número de espacios menor que
1: "
+ lines[line.lineNumber-1]);
}
else if(lastESPContent + line.address + a > Instruction.Memory_Address_Limit)
{
throw new Exception("Error en línea " + line.lineNumber +
" : Añadir '" + (int)(a+1) +
"' espacios no es posible porque no hay memoria suficiente: "
+ lines[line.lineNumber-1]);
}
220
else
{
lastESPContent += a;
line.instruction.setAddressLocation(line.address);
}
}
else
{
line.address = lastORGContent + lastESPContent + indexCounter - lastORGIndex;
line.instruction.setAddressLocation(line.address);
}
indexCounter++;
}
//Ahora sustituimos las etiquetas por direcciones de memoria
lineCounter = 0;
for(LineCode line: lineCodeArray)
{
if(line.label != null)
{
try {
int a = Integer.parseInt(line.label);
throw new Exception("Error en línea " + line.lineNumber +
" : La etiqueta '" + a + "' no puede ser un número: " +
lines[line.lineNumber-1]);
}
catch (NumberFormatException e)
{
searchLabel(lineCodeArray, line.label);
}
}
if(line.addressLabel != null && line.pseudoInstruction == null)
{
int address = searchLabel(lineCodeArray, line.addressLabel);
if(address > 0 )
{
line.instruction.setInstructionOperator(address);
}
else if (address == -1)
{
//Comprobar si la etiqueta es un número
try {
address = Integer.parseInt(line.addressLabel);
}
catch(Exception e) {
throw new Exception("Error en línea " + line.lineNumber +
" : Etiqueta '" + line.addressLabel + "' no encontrada: " +
lines[line.lineNumber - 1]);
}
int r = line.instruction.setInstructionOperator(address);
if( r == -1)
{
throw new Exception("Error en línea " + line.lineNumber +
" : Dirección de memoria '" + line.addressLabel + "' fuera
de rango: "
+ lines[line.lineNumber - 1]);
}
else
{
//Todo ok
}
}
}
else if(line.addressLabel != null && line.pseudoInstruction == PseudoInstruction.DRE)
{
int address = searchLabel(lineCodeArray, line.addressLabel);
if(address > 0 )
{
line.instruction.setInstructionOperator(address);
}
else if (address == -1)
{
//Comprobar si la etiqueta es un número
try {
address = Integer.parseInt(line.addressLabel);
}
catch(Exception e) {
throw new Exception("Error en línea " + line.lineNumber +
" : Etiqueta '" + line.addressLabel + "' no encontrada: "
+ lines[line.lineNumber - 1]);
}
throw new Exception("Error en línea " + line.lineNumber +
" : El operador '" + line.addressLabel +
"' de la pseudoinstrucción ha de ser una etiqueta: "
+ lines[line.lineNumber - 1]);
}
221
}
lineCounter++;
}
int okay = 0;
for(LineCode line: lineCodeArray)
{
okay = line.check();
switch(okay)
{
case 0:
break;
case -1:
throw new Exception("Error: número de línea negativo " + line.lineNumber);
case -2:
throw new Exception("Error en la línea " + line.lineNumber +
" : memoria fuera de rango" );
case -3:
throw new Exception("Error en la línea " + line.lineNumber +
" : pseudoInstruction e instruction nulos! ");
case -4:
throw new Exception("Error: número de línea negativo " + line.lineNumber +
" : Pseudoinstrucción FIN no procesada correctamente");
default:
throw new Exception("Error no reconocido");
}
}
//Rellenamos el array de instrucciones
for(LineCode line: lineCodeArray)
{
if(line.pseudoInstruction != null)
{
switch(line.pseudoInstruction)
{
case ORG:
case FIN:
case ESP:
case CTE:
case DRE:
//Todo OK
break;
//No deberíamos haber guardado esta pseudo instrucción!!
throw new Exception("Error: número de línea negativo" + line.lineNumber +
" : Pseudoinstrucción FIN no procesada correctamente");
array.add(line.instruction);
break;
array.add(line.instruction);
break;
array.add(line.instruction);
break;
}
}
else if(line.instruction != null && line.instruction.isInstruction())
{
array.add(line.instruction);
}
}
return array;
}
/**
* @brief Busca una etiqueta en una lista de líneas de código.
*/
private static int searchLabel(ArrayList<LineCode> lineCodeArray, String addressLabel) throws Exception
{
int indexCounter = 0;
int out = -1; //Etiqueta no encontrada
int lastMod = 0;
for(LineCode line: lineCodeArray)
{
if(addressLabel.equals(line.label))
{
if(out != -1)
{
throw new Exception("Error en línea " + lineCodeArray.get(lastMod).lineNumber
" : etiqueta '" + line.label + "' duplicada en la línea: "
+ line.lineNumber);
}
else
{
lastMod = indexCounter;
out = line.address;
}
}
indexCounter++;
}
return out;
222
+
}
/**
* @brief Traduce a binario un programa, una vez tenemos las instrucciones que lo forman.
* Este es el principal método que permite guardar en formato “ece” el código binario de un programa.
*/
public static byte[] translateToBinary(ArrayList<Instruction> code)
{
byte[] binary = new byte[(Instruction.Memory_Address_Limit+1)*2];
int foo = 0;
for(Instruction i: code)
{
foo = i.getDataUnsigned();
//BigEndian or LittleEndian?
binary[i.getAddressLocation()*2] = intToByte(foo & 0x00FF);
binary[i.getAddressLocation()*2 + 1] = intToByte((foo & 0xFF00) >> 8);
}
return binary;
}
/**
* @brief Método usado para convertir de int a byte.
*/
public static byte intToByte(int i)
{
return (byte)i;
}
/**
* @brief Método usado para convertir de byte a int.
*/
public static int byteToInt(byte b)
{
int i = (byte)b;
if(b < 0)
{
i = i - 2*((int)Byte.MIN_VALUE);
}
return i;
}
/**
* @brief Traduce código binario a un mapa de memoria que contiene un programa.
* Es el método principal a la hora de leer código binario y traducirlo a instrucciones
* que entienda el computador virtual Xenon.
*/
public static ArrayList<Instruction> translateFromBinary(byte[] binary)
{
ArrayList<Instruction> array = new ArrayList<Instruction>();
int foo = 0;
Instruction sr;
for(int i = 0; i < binary.length/2; i++)
{
//BigEndian or LittleEndian?
foo= byteToInt(binary[i*2]) + (byteToInt(binary[i*2 + 1]) << 8);
if(foo != 0)
{
sr = new Instruction();
try{
sr.setInstructionUnsigned(foo);
sr.setAddressLocation(i);
}
catch(Exception e)
{
}
array.add(sr);
}
}
return array;
}
/**
* @brief Abre un fichero binario y devuelve el mapa de instrucciones.
* @param file
* @return
* @throws Exception
* @throws FileNotFoundException
*/
public static ArrayList<Instruction> openBinaryFile(File file) throws Exception, FileNotFoundException
{
long lSize=file.length();
int size= (int)lSize;
if(lSize > Integer.MAX_VALUE)
{
throw new Exception("File is too big");
}
223
byte[] contents=new byte[size];
try
{
FileInputStream fis =
new FileInputStream(file);
fis.read(contents, 0, size);
fis.close();
}
catch (FileNotFoundException e){
throw e;
}
}
return translateFromBinary(contents);
/**
* @brief Guarda el código binario de un programa en formato "ece".
* @param file
* @param ins
* @throws IOException
* @throws FileNotFoundException
*/
public static void saveToBinaryFile(File file, ArrayList<Instruction> ins) throws IOException, FileNotFoundException
{
byte[] contents = translateToBinary(ins);
try
{
FileOutputStream fos = new FileOutputStream(file);
fos.write(contents, 0, contents.length);
fos.flush();
fos.close();
}
catch (FileNotFoundException e){
throw e;
}
catch (IOException e){
throw e;
}
}
}
224
11.1.18 Interface.java
package xenon;
import java.awt.Container;
import java.awt.EventQueue;
import java.awt.Rectangle;
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
javax.swing.AbstractAction;
javax.swing.Action;
javax.swing.ImageIcon;
javax.swing.JCheckBox;
javax.swing.JDialog;
javax.swing.JFrame;
javax.swing.JLabel;
javax.swing.JMenu;
javax.swing.JMenuBar;
javax.swing.JMenuItem;
javax.swing.JOptionPane;
javax.swing.JPanel;
javax.swing.JPopupMenu;
javax.swing.JScrollPane;
javax.swing.JSlider;
javax.swing.JSplitPane;
javax.swing.JTabbedPane;
javax.swing.JTextArea;
javax.swing.JToolBar;
javax.swing.JTree;
javax.swing.KeyStroke;
javax.swing.JButton;
java.awt.event.ActionEvent;
java.awt.event.KeyEvent;
java.awt.event.MouseListener;
java.awt.event.MouseWheelEvent;
java.awt.event.MouseWheelListener;
import
import
import
import
javax.swing.GroupLayout;
javax.swing.GroupLayout.Alignment;
javax.swing.event.ChangeEvent;
javax.swing.event.ChangeListener;
import
import
import
import
import
java.awt.CardLayout;
java.io.BufferedReader;
java.io.File;
java.io.FileReader;
java.util.ArrayList;
// Font source: http://art.gnome.org/themes/icon?page=2
// License: GPL
/**
* @brief Vista principal del entorno de desarrollo
* @details
* En esta clase se encuentra el main(). Permite conmutar entre las vistas de desarrollo y depuración,
* así como entrar en la vista de emulación.
*
*/
public class Interface extends JFrame {
/**
*
* @brief Listener que actualiza la frecuencia de ejecución cuando cambia el slider.
*
*/
class SliderListener implements ChangeListener {
//Etiqueta que muestra al usuario la frecuencia escogida.
private JLabel label;
DebugViewManager manager;
SliderListener(JLabel l, DebugViewManager dvm)
{
label = l;
manager = dvm;
}
@Override
public void stateChanged(ChangeEvent arg0) {
JSlider source = (JSlider)arg0.getSource();
long hz = (long)source.getValue();
label.setText(hz + " Hz");
if (!source.getValueIsAdjusting() && manager != null) {
//Usamos 1000/f porque la función setExecutionPeriod hace uso de T=milisegundos.
manager.setExecutionPeriod(1000L/hz);
}
}
}
/**
*
*/
private static final long serialVersionUID = 1L;
JPanel cardPanel; //Panel que usa CardLayout para cambiar entre la vista de depuración y de código.
225
final static String CODEVIEW = "Code";
final static String DEBUGVIEW = "Debug";
String state = CODEVIEW; //Variable que informa de si estamos actualmente en la vista de código o de depuración
JTree projectsTree; //Árbol de proyectos
TabsManager tabsManager;
//Gestor de pestañas.
DebugViewManager debugViewManager; //Controlador principal de la vista de depuración
JTextArea problemasArea; //Área que informa de problemas en la vista de desarrollo
JLabel time;
//CesiusHelper core;
ProjectsManager projectsManager;
JSlider slider; //Slider que sirve para cambiar la frecuencia de ejecución del computador.
/**
* @brief Añade todos los componentes necesarios al panel.
* @param pane
*/
public void addComponentToPane(Container pane) {
debugViewManager = new DebugViewManager();
//Este panel contiene la vista de desarrollo
JPanel codeJPanel = new JPanel();
//Barra de menú de la vista de desarrollo
JMenuBar menuBarCodeView = new JMenuBar();
JMenu menu, submenu;
JMenuItem menuItem;
JToolBar toolBar;
JButton button;
ImageIcon icon;
//A continuación definimos todas las acciones de la vista de código/desarrollo
java.net.URL imageURL = Interface.class.getResource("images/window-new.png");
icon = new ImageIcon(imageURL);
Action actionNuevoProyecto = new AbstractAction("Nuevo Proyecto", icon) {
/**
*
*/
private static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent e) {
projectsManager.createProject();
}
};
imageURL = Interface.class.getResource("images/document-save.png");
icon = new ImageIcon(imageURL);
Action actionGuardar = new AbstractAction("Guardar", icon) {
/**
*
*/
private static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent e) {
tabsManager.saveCurrentlySelectedTab();
}
};
imageURL = Interface.class.getResource("images/gnome-fs-directory.png");
icon = new ImageIcon(imageURL);
Action actionAbrirProyecto = new AbstractAction("Abrir Proyecto", icon) {
/**
*
*/
private static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent e) {
projectsManager.openProject();
}
};
imageURL = Interface.class.getResource("images/gtk-close.png");
icon = new ImageIcon(imageURL);
Action actionCerrarProyecto = new AbstractAction("Cerrar Proyecto", icon) {
/**
*
*/
private static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent e) {
projectsManager.closeProject();
}
};
imageURL = Interface.class.getResource("images/document-save-as.png");
icon = new ImageIcon(imageURL);
Action actionGuardarComo = new AbstractAction("Guardar Como...", icon) {
226
/**
*
*/
private static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent e) {
tabsManager.saveCurrentlySelectedTabAs();
}
};
imageURL = Interface.class.getResource("images/stock_data-linked-table.png");
icon = new ImageIcon(imageURL);
Action actionGuardarTodo = new AbstractAction("Guardar Todo", icon) {
/**
*
*/
private static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent e) {
tabsManager.saveAllTabs();
}
};
imageURL = Interface.class.getResource("images/gtk-quit.png");
icon = new ImageIcon(imageURL);
Action actionSalir = new AbstractAction("Salir", icon) {
/**
*
*/
private static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
};
imageURL = Interface.class.getResource("images/gtk-delete.png");
icon = new ImageIcon(imageURL);
Action actionEliminarFichero = new AbstractAction("Eliminar Fichero", icon) {
/**
*
*/
private static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent e) {
//Adquirimos la información del fichero actualmente seleccionado en el árbol de ficheros
ProjectFile currentFile = projectsManager.getCurrentlySelectedFileInJTree();
Object[] options = {"OK",
"Cancelar"};
if(currentFile != null)
{
//Preguntamos al usuario si realmente desea eliminar el fichero
int n = JOptionPane.showOptionDialog(null, "Desea eliminar " +
currentFile.file.getName() +
" del sistema?",
"Confirme borrado",JOptionPane.OK_CANCEL_OPTION,
JOptionPane.QUESTION_MESSAGE,
null, options, options[1]);
if(n == JOptionPane.OK_OPTION)
{
//Lo eliminamos de la lista de pestañas así como del árbol de ficheros
tabsManager.dontAskAndRemoveTab(tabsManager.searchTab(currentFile));
projectsManager.removeFileFromJTree(currentFile);
try{
//Eliminamos el fichero del sistema de archivos/disco duro.
currentFile.file.delete();
} catch (Exception x) {
problemasArea.append(x.getMessage() + "\n");
}
}
}
}
};
imageURL = Interface.class.getResource("images/stock_compile.png");
icon = new ImageIcon(imageURL);
Action actionCompilar = new AbstractAction("Compilar", icon) {
/**
*
*/
private static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent e) {
if(state.compareTo(CODEVIEW) == 0)
{
/*
* Primero intentamos seleccionar para compilar la pestaña actual;
* Si no es código o no hay ninguna pestaña seleccionada, comprobamos si hay
* algún fichero de código seleccionado en el árbol de ficheros. En última instancia
227
* seleccionamos el fichero de código del actual proyecto.
*/
ProjectFile codeToCompile = null;
Tab currentTab = tabsManager.getCurrentlySelectedTab();
ProjectFile currentFile = projectsManager.getCurrentlySelectedFileInJTree();
if(currentTab != null && currentTab.pFile.type == ProjectFile.FileType.CODE)
{
codeToCompile = currentTab.pFile;
}
else if(currentFile != null
&& currentFile.type == ProjectFile.FileType.CODE)
{
codeToCompile = currentFile;
}
else
{
Project p = projectsManager.getCurrentlySelectedProject();
if(p != null)
{
for(ProjectFile pFile: p.projectFiles)
{
if(pFile.type == ProjectFile.FileType.CODE)
{
codeToCompile = pFile;
break;
}
}
}
}
if(codeToCompile != null)
{
//Si el archivo ha sido modificado, preguntar si el usuario quiere guardarlo
antes de compilar
tabsManager.saveIfModified(codeToCompile);
//Leer el fichero
String code = "";
try {
String strLine;
BufferedReader br = new BufferedReader(new
FileReader(codeToCompile.file));
while((strLine = br.readLine()) != null)
{
code += strLine + "\n";
}
}
catch(Exception ex)
{
}
System.err.println("Error: " + ex.getMessage());
//Traducir a instrucciones y guardarlas en formato binario
try
{
/**
* Si el archivo seleccionado para compilar se llama X.ls2, esta
* función añadirá al proyecto el archivo binario X.ece.
*/
File f = projectsManager.addBinaryFromCode(codeToCompile);
if(!f.exists())
{
//Crear el fichero
f.createNewFile();
}
//Crear el código binario, guardarlo, y avisar de que todo ha ido
bien.
XenonHelper.saveToBinaryFile(f,
XenonHelper.translateToInstructions(code) );
problemasArea.append("Compilación de "
+
codeToCompile.file.getName() +
" correcta y guardada en "
}
catch(Exception ce)
{
problemasArea.append(ce.getMessage() + "\n");
}
}
}
}
};
imageURL = Interface.class.getResource("images/stock_smart-playlist.png");
icon = new ImageIcon(imageURL);
Action actionDepurar = new AbstractAction("Depurar", icon) {
/**
*
*/
private static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent e) {
//state = !state;
228
+ f.getName() +"\n");
ProjectFile.FileType.BINARY)
if(state.compareTo(CODEVIEW) == 0)
{
ProjectFile codeToDebug = null;
/*
* Primero intentamos seleccionar para depurar la pestaña actual;
* Si no es código o binario, o no hay ninguna pestaña seleccionada, comprobamos si hay
* algún fichero de código seleccionado en el árbol de ficheros. En última instancia
* seleccionamos el fichero de código del actual proyecto.
*/
Tab currentTab = tabsManager.getCurrentlySelectedTab();
ProjectFile currentFile = projectsManager.getCurrentlySelectedFileInJTree();
if(currentTab != null && (currentTab.pFile.type == ProjectFile.FileType.CODE
|| currentTab.pFile.type == ProjectFile.FileType.BINARY))
{
codeToDebug = currentTab.pFile;
}
else if(currentFile != null && (currentFile.type == ProjectFile.FileType.CODE ||
currentFile.type == ProjectFile.FileType.BINARY))
{
codeToDebug = currentFile;
}
else
{
Project p = projectsManager.getCurrentlySelectedProject();
if(p != null)
{
for(ProjectFile pFile: p.projectFiles)
{
if(pFile.type == ProjectFile.FileType.CODE ||
pFile.type ==
{
codeToDebug = pFile;
break;
}
}
}
}
if(codeToDebug != null && codeToDebug.type == ProjectFile.FileType.CODE)
{
//Comprobar si el fichero ha sido modificado y preguntar al usuario si quiere
guardarlo
tabsManager.saveIfModified(codeToDebug);
//Leer el fichero
String code = "";
try {
String strLine;
BufferedReader br = new BufferedReader(new FileReader(codeToDebug.file));
while((strLine = br.readLine()) != null)
{
code += strLine + "\n";
}
}
catch(Exception ex)
{
System.err.println("Error: " + ex.getMessage());
problemasArea.append(ex.getMessage() + "\n");
}
//Traducirlo a instrucciones
ArrayList<Instruction> in = null;
try
{
//Cargar el programa en el gestor de la vista de depuración, y abrir
dicha vista
in =
XenonHelper.generateMemoryMap(XenonHelper.translateToInstructions(code));
debugViewManager.setDebugCode(in, codeToDebug.file);
setTitle("CESIUS IDE - " + codeToDebug.file.getPath());
state = DEBUGVIEW;
}
catch(Exception ce)
{
System.out.println(ce.getMessage());
problemasArea.append(ce.getMessage() + "\n");
}
System.out.println("Debugging code: " + codeToDebug.file.getName());
//Add those instructions to the debug
}
else if(codeToDebug != null && codeToDebug.type == ProjectFile.FileType.BINARY)
{
try {
//Cargar binario en la vista de depuración
ArrayList<Instruction> in =
XenonHelper.openBinaryFile(codeToDebug.file);
debugViewManager.setDebugCode(in, codeToDebug.file);
state = DEBUGVIEW;
System.out.println("Debugging binary: " +
codeToDebug.file.getName());
setTitle("CESIUS IDE - " + codeToDebug.file.getPath());
}
catch(Exception x){
229
System.out.println(x.getMessage());
problemasArea.append(x.getMessage() + "\n");
}
}
}
else if(state.compareTo(DEBUGVIEW) == 0)
{
state = CODEVIEW;
setTitle("CESIUS IDE");
}
CardLayout ml = (CardLayout)(cardPanel.getLayout());
//Cargar la vista actual
ml.show(cardPanel, state);
}
};
imageURL = Interface.class.getResource("images/stock_data-next.png");
icon = new ImageIcon(imageURL);
Action actionEjecutar = new AbstractAction("Ejecutar", icon) {
/**
*
*/
private static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent e) {
Emulator sim = new Emulator();
ProjectFile codeToExecute = null;
/*
* Primero intentamos seleccionar para depurar la pestaña actual;
* Si no es código o binario, o no hay ninguna pestaña seleccionada, comprobamos si hay
* algún fichero de código seleccionado en el árbol de ficheros. En última instancia
* seleccionamos el fichero de código del actual proyecto.
*/
Tab currentTab = tabsManager.getCurrentlySelectedTab();
ProjectFile currentFile = projectsManager.getCurrentlySelectedFileInJTree();
if(currentTab != null && (currentTab.pFile.type == ProjectFile.FileType.BINARY))
{
codeToExecute = currentTab.pFile;
}
else if(currentFile != null && (currentFile.type == ProjectFile.FileType.BINARY))
{
codeToExecute = currentFile;
}
else
{
Project p = projectsManager.getCurrentlySelectedProject();
if(p != null)
{
for(ProjectFile pFile: p.projectFiles)
{
if(pFile.type == ProjectFile.FileType.BINARY)
{
codeToExecute = pFile;
break;
}
}
}
}
if(codeToExecute != null && codeToExecute.type == ProjectFile.FileType.BINARY)
{
try {
//Leer las instrucciones del archivo binario y abrir el emulador.
ArrayList<Instruction> in = XenonHelper.openBinaryFile(codeToExecute.file);
sim.setRunCode(in);
sim.setMyTitle(codeToExecute.file.getPath());
System.out.println("Running binary: " + codeToExecute.file.getName());
sim.setVisible(true);
}
catch(Exception x){
System.out.println(x.getMessage());
problemasArea.append(x.getMessage() + "\n");
}
}
}
};
imageURL = Interface.class.getResource("images/gtk-close.png");
icon = new ImageIcon(imageURL);
Action actionCerrarFichero = new AbstractAction("Cerrar Fichero", icon) {
/**
*
*/
private static final long serialVersionUID = 1L;
230
public void actionPerformed(ActionEvent e) {
tabsManager.closeCurrentlySelectedTab();
}
};
imageURL = Interface.class.getResource("images/gtk-close.png");
icon = new ImageIcon(imageURL);
Action actionCerrarTodos = new AbstractAction("Cerrar Todos", icon) {
/**
*
*/
private static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent e) {
tabsManager.closeAllTabs();
}
};
Action actionLimpiarProblemas = new AbstractAction("Limpiar", null) {
/**
*
*/
private static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent e) {
problemasArea.setText("");
}
};
imageURL = Interface.class.getResource("images/help.png");
icon = new ImageIcon(imageURL);
Action actionSobre = new AbstractAction("Sobre este programa...", icon) {
/**
*
*/
private static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent e) {
Rectangle r = getBounds();
Sobre dialog = new Sobre(r.x, r.y);
dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
dialog.setVisible(true);
}
};
//Creamos la barra de menú de la vista de código/desarrollo
menu = new JMenu("Archivo");
menuBarCodeView.add(menu);
menuItem = menu.add(actionNuevoProyecto);
menu.add(menuItem);
menu.addSeparator();
menuItem = menu.add(actionCerrarFichero);
menu.add(menuItem);
menuItem = menu.add(actionCerrarTodos);
menu.add(menuItem);
menuItem = menu.add(actionEliminarFichero);
menu.add(menuItem);
menu.addSeparator();
menuItem = menu.add(actionGuardar);
menuItem.setAccelerator(KeyStroke.getKeyStroke(
KeyEvent.VK_S, ActionEvent.CTRL_MASK));
menu.add(menuItem);
menuItem = menu.add(actionGuardarComo);
menu.add(menuItem);
menuItem = menu.add(actionGuardarTodo);
menu.add(menuItem);
menu.addSeparator();
menuItem = menu.add(actionSalir);
menuItem.setAccelerator(KeyStroke.getKeyStroke(
KeyEvent.VK_ESCAPE, ActionEvent.CTRL_MASK));
menu.add(menuItem);
//////////
menu = new JMenu("Proyecto");
menuBarCodeView.add(menu);
menuItem = menu.add(actionAbrirProyecto);
231
menu.add(menuItem);
menuItem = menu.add(actionCerrarProyecto);
menu.add(menuItem);
menu.addSeparator();
menuItem = menu.add(actionCompilar);
menuItem.setAccelerator(KeyStroke.getKeyStroke(
KeyEvent.VK_B, ActionEvent.CTRL_MASK));
menu.add(menuItem);
menuItem = menu.add(actionDepurar);
menuItem.setAccelerator(KeyStroke.getKeyStroke(
KeyEvent.VK_D, ActionEvent.CTRL_MASK));
menu.add(menuItem);
menuItem = menu.add(actionEjecutar);
menuItem.setAccelerator(KeyStroke.getKeyStroke(
KeyEvent.VK_E, ActionEvent.CTRL_MASK));
menu.add(menuItem);
///////////
menu = new JMenu("Ayuda");
menuBarCodeView.add(menu);
menuItem = menu.add(actionSobre);
menu.add(menuItem);
////////////
//Creamos la barra de herramientas de la vista de desarrollo
toolBar = new JToolBar();
toolBar.setFloatable(false);
button = toolBar.add(actionNuevoProyecto);
button.setToolTipText("Nuevo Fichero");
button = toolBar.add(actionGuardar);
button.setToolTipText("Guardar");
button = toolBar.add(actionGuardarComo);
button.setToolTipText("Guardar Como...");
button = toolBar.add(actionGuardarTodo);
button.setToolTipText("Guardar Todo");
button = toolBar.add(actionAbrirProyecto);
button.setToolTipText("Abrir Proyecto");
button = toolBar.add(actionCerrarProyecto);
button.setToolTipText("Cerrar Proyecto");
button = toolBar.add(actionCompilar);
button.setToolTipText("Compilar");
button = toolBar.add(actionDepurar);
button.setToolTipText("Depurar");
button = toolBar.add(actionEjecutar);
button.setToolTipText("Ejecutar");
////////////
/*
* splitPane es un panel dividido de forma que en su parte izquierda tiene el árbol de archivos,
* y en su parte derecha están las pestañas de los archivos abiertos y el panel de problemas.
*/
JSplitPane splitPane = new JSplitPane();
splitPane.setResizeWeight(0.15);
//El árbol de archivos ha de estar dentro de un panel que permita el desplazamiento horiz/vertical.
JScrollPane scrollPane = new JScrollPane();
splitPane.setLeftComponent(scrollPane);
//rightSplitPane contiene el panel de problemas y las pestañas de archivos abiertos.
JSplitPane rightSplitPane = new JSplitPane();
rightSplitPane.setResizeWeight(0.8);
rightSplitPane.setOrientation(JSplitPane.VERTICAL_SPLIT);
splitPane.setRightComponent(rightSplitPane);
JTabbedPane tabbedFilePane = new JTabbedPane(JTabbedPane.TOP);
//Iniciamos el gestor de pestañas
tabsManager = new TabsManager(tabbedFilePane);
rightSplitPane.setLeftComponent(tabbedFilePane);
projectsManager = new ProjectsManager(tabsManager);
232
scrollPane.setViewportView(projectsManager.getProjectsTree());
//El panel de problemas estará dentro de una pestaña
JTabbedPane tabbedPane_1 = new JTabbedPane(JTabbedPane.TOP);
rightSplitPane.setRightComponent(tabbedPane_1);
problemasArea = new JTextArea();
problemasArea.setEditable(false);
JScrollPane scrollPane_2 = new JScrollPane(problemasArea);
tabbedPane_1.addTab("Problemas", null, scrollPane_2, null);
//Creamos un menú vinculado al panel de problemas para poder vaciar dicho panel
JPopupMenu popup = new JPopupMenu();
popup.add(actionLimpiarProblemas);
MouseListener popupListener = new PopupListener(popup);
problemasArea.addMouseListener(popupListener);
//Aquí definimos la disposición gráfica de los componentes en la vista de desarrollo.
GroupLayout gl_menu1 = new GroupLayout(codeJPanel);
gl_menu1.setHorizontalGroup(
gl_menu1.createParallelGroup(Alignment.LEADING)
.addComponent(menuBarCodeView, 0, 1060, Short.MAX_VALUE)
.addComponent(toolBar, 0, 1060, Short.MAX_VALUE)
.addComponent(splitPane, 0, 1060, Short.MAX_VALUE)
);
gl_menu1.setVerticalGroup(
gl_menu1.createParallelGroup(Alignment.LEADING)
.addGroup(gl_menu1.createSequentialGroup()
.addComponent(menuBarCodeView, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE,
GroupLayout.PREFERRED_SIZE)
.addComponent(toolBar, GroupLayout.PREFERRED_SIZE, 24, GroupLayout.PREFERRED_SIZE)
.addComponent(splitPane, 0, 560, Short.MAX_VALUE)
)
);
codeJPanel.setLayout(gl_menu1);
//////////////
//Panel que contendrá toda la vista de depuración.
JPanel debugJPanel = new JPanel();
//Barra de menús de la vista de depuración.
JMenuBar menuBarDebug = new JMenuBar();
//A continuación definimos todas las acciones de la vista de depuración.
imageURL = Interface.class.getResource("images/player_play.png");
icon = new ImageIcon(imageURL);
Action actionEjecutarIns = new AbstractAction("Ejecutar Instrucción", icon) {
/**
*
*/
private static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent e) {
debugViewManager.actionExecuteNextInstruction();
}
};
imageURL = Interface.class.getResource("images/player_end.png");
icon = new ImageIcon(imageURL);
Action actionEjecutarHasta = new AbstractAction("Ejecutar Hasta...", icon) {
/**
*
*/
private static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent e) {
String s = (String)JOptionPane.showInputDialog(
null,
"Ejecutar hasta la instrucción en la posición de memoria:\n",
"Introduzca dato",
JOptionPane.PLAIN_MESSAGE,
new ImageIcon(),
null,
"0");
if(s.compareTo("") != 0)
{
int num = Integer.parseInt(s);
System.out.println("Ejecutar hasta la instrucción "+ num);
if(num >= 0 && num <= Instruction.Memory_Address_Limit)
{
debugViewManager.actionRunTo(num);
}
}
}
};
imageURL = Interface.class.getResource("images/reload.png");
icon = new ImageIcon(imageURL);
Action actionReiniciar = new AbstractAction("Comenzar de nuevo", icon) {
/**
233
*
*/
private static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent e) {
debugViewManager.actionRestart();
}
};
imageURL = Interface.class.getResource("images/player_fwd.png");
icon = new ImageIcon(imageURL);
Action actionEjecutarTodo = new AbstractAction("Ejecutar Todo", icon) {
/**
*
*/
private static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent e) {
debugViewManager.actionRun();
}
};
imageURL = Interface.class.getResource("images/player_pause.png");
icon = new ImageIcon(imageURL);
Action actionPausar = new AbstractAction("Pausar", icon) {
/**
*
*/
private static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent e) {
debugViewManager.actionPause();
}
};
Action actionBinario = new AbstractAction("Binario", null) {
/**
*
*/
private static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent e) {
}
debugViewManager.setRegistersBase(DebugViewManager.Base.BINARY);
};
Action actionDecimal = new AbstractAction("Decimal", null) {
/**
*
*/
private static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent e) {
}
debugViewManager.setRegistersBase(DebugViewManager.Base.DECIMAL);
};
Action actionHexadecimal = new AbstractAction("Hexadecimal", null) {
/**
*
*/
private static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent e) {
}
debugViewManager.setRegistersBase(DebugViewManager.Base.HEXADECIMAL);
};
menu = new JMenu("Archivo");
menuBarDebug.add(menu);
menuItem = menu.add(actionSalir);
menuItem.setAccelerator(KeyStroke.getKeyStroke(
KeyEvent.VK_ESCAPE, ActionEvent.CTRL_MASK));
menu.add(menuItem);
//////////////
menu = new JMenu("Vista");
menuBarDebug.add(menu);
menuItem = menu.add(actionDepurar);
menuItem.setText("Salir del modo depuración");
menuItem.setAccelerator(KeyStroke.getKeyStroke(
KeyEvent.VK_F, ActionEvent.CTRL_MASK));
menu.add(menuItem);
menu.addSeparator();
submenu = new JMenu("Base");
234
menu.add(submenu);
submenu.add(actionBinario);
submenu.add(actionDecimal);
submenu.add(actionHexadecimal);
//////////////
menu = new JMenu("Operaciones");
menuBarDebug.add(menu);
menuItem = menu.add(actionEjecutarIns);
menuItem.setAccelerator(KeyStroke.getKeyStroke(
KeyEvent.VK_S, ActionEvent.CTRL_MASK));
menu.add(menuItem);
menuItem = menu.add(actionEjecutarHasta);
menuItem.setAccelerator(KeyStroke.getKeyStroke(
KeyEvent.VK_H, ActionEvent.CTRL_MASK));
menu.add(menuItem);
menuItem = menu.add(actionReiniciar);
menuItem.setAccelerator(KeyStroke.getKeyStroke(
KeyEvent.VK_Q, ActionEvent.CTRL_MASK));
menu.add(menuItem);
menuItem = menu.add(actionEjecutarTodo);
menuItem.setAccelerator(KeyStroke.getKeyStroke(
KeyEvent.VK_R, ActionEvent.CTRL_MASK));
menu.add(menuItem);
menuItem = menu.add(actionPausar);
menuItem.setAccelerator(KeyStroke.getKeyStroke(
KeyEvent.VK_P, ActionEvent.CTRL_MASK));
menu.add(menuItem);
//////////////
//Definimos la barra de herramientas de la vista de depuración.
toolBar = new JToolBar();
toolBar.setFloatable(false);
button = toolBar.add(actionEjecutarIns);
button.setToolTipText("Ejecutar Instrucción");
button = toolBar.add(actionEjecutarHasta);
button.setToolTipText("Ejecutar Hasta...");
button = toolBar.add(actionReiniciar);
button.setToolTipText("Comenzar de nuevo");
button = toolBar.add(actionEjecutarTodo);
button.setToolTipText("Ejecutar Todo");
button = toolBar.add(actionPausar);
button.setToolTipText("Pausar");
button = toolBar.add(actionDepurar);
button.setToolTipText("Salir del modo depuración");
JLabel timeLabel = new JLabel(" T: ");
JCheckBox checkBox = new JCheckBox();
checkBox.addItemListener(debugViewManager);
JLabel checkBoxLabel = new JLabel("Ejecutar en 2 pasos");
time = new JLabel("000000 ms");
time.setToolTipText("Tiempo de ejecución");
debugViewManager.timeLabel = time;
slider = new JSlider(JSlider.HORIZONTAL,
1, 1000, 2);
slider.setToolTipText("Frecuencia del procesador");
//Etiqueta que muestra al usuario la frecuencia escogida.
JLabel l = new JLabel("2 Hz");
l.setToolTipText("Frecuencia del procesador");
//El listener detectará que el slider ha cambiado y modificará la frecuencia del procesador
SliderListener slistener = new SliderListener(l, debugViewManager);
slider.addChangeListener(slistener);
//Este listener sirve para poder mover el slider con la rueda del ratón
slider.addMouseWheelListener(new MouseWheelListener() {
@Override
public void mouseWheelMoved(MouseWheelEvent arg0) {
if(slider != null)
{
int notches = arg0.getWheelRotation();
if (notches < 0) {
slider.setValue(slider.getValue() + 1);
} else {
slider.setValue(slider.getValue() - 1);
}
}
}
235
});
toolBar.add(timeLabel);
toolBar.add(time);
toolBar.add(checkBox);
toolBar.add(checkBoxLabel);
toolBar.add(slider);
toolBar.add(l);
//Definimos la disposición de los componentes de la vista de depuración.
GroupLayout gl_menu2 = new GroupLayout(debugJPanel);
gl_menu2.setHorizontalGroup(
gl_menu2.createParallelGroup(Alignment.LEADING)
.addComponent(menuBarDebug, 0, 1060, Short.MAX_VALUE)
.addComponent(toolBar, 0, 1060, Short.MAX_VALUE)
.addComponent(debugViewManager, 0, 1060, Short.MAX_VALUE)
);
gl_menu2.setVerticalGroup(
gl_menu2.createParallelGroup(Alignment.LEADING)
.addGroup(gl_menu2.createSequentialGroup()
.addComponent(menuBarDebug, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE,
GroupLayout.PREFERRED_SIZE)
.addComponent(toolBar, GroupLayout.PREFERRED_SIZE, 24, GroupLayout.PREFERRED_SIZE)
.addComponent(debugViewManager, 0, 692, Short.MAX_VALUE))
);
debugJPanel.setLayout(gl_menu2);
//Instanciamos el panel que contiene ambas vistas.
cardPanel = new JPanel(new CardLayout());
cardPanel.add(codeJPanel, CODEVIEW);
cardPanel.add(debugJPanel, DEBUGVIEW);
//Añadimos dicho panel al panel principal
pane.add(cardPanel);
}
/**
* @brief Lanza la aplicación
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Interface frame = new Interface();
frame.pack();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Crear el frame
*/
public Interface() {
//core = new CesiusHelper();
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Definimos la posición en pantalla y el tamaño de la ventana.
setBounds(100, 100, 1060, 750);
setTitle("CESIUS IDE");
addComponentToPane(getContentPane());
}
}
236
Descargar