Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added .DS_Store
Binary file not shown.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Binary file added modular/.DS_Store
Binary file not shown.
33 changes: 33 additions & 0 deletions modular/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# MIC-1 Simulador Modular

Refatoração modular do simulador de microprogramação baseado na arquitetura MIC-1.

## 🔧 O que foi feito

- Separação do código original monolítico (`Emulador.c`) em módulos independentes
- Estrutura com `main.c`, `cpu.c`, `memoria.c`, etc.
- Suporte a microprograma binário (`microprog.rom`)
- Assembler simples em Python
- Exemplo funcional (`PUSH`, `ADD`, `PRINT`)

## ▶️ Como usar

### Compilar:

```bash
make




Esse Makefile funciona dentro da pasta modular/. Use assim:

bash
Copiar
Editar
cd modular
make
./simulador programa.bin



44 changes: 44 additions & 0 deletions modular/assembler.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import struct

# Mapeamento de instruções para opcodes
INSTRUCOES = {
'PUSH': 0x01,
'ADD': 0x02,
'PRINT': 0x03,
}

def montar_instrucao(linha):
partes = linha.strip().split()
if not partes:
return []

instr = partes[0].upper()

if instr == 'PUSH':
valor = int(partes[1])
return [INSTRUCOES['PUSH'], valor]
elif instr in INSTRUCOES:
return [INSTRUCOES[instr]]
else:
raise ValueError(f"Instrução desconhecida: {instr}")

def montar_programa(arquivo_entrada, arquivo_saida):
codigo = []

with open(arquivo_entrada, 'r') as fonte:
for linha in fonte:
instrucao = montar_instrucao(linha)
codigo.extend(instrucao)

header = [0] * 20 # inicialização de 20 bytes
tamanho_total = 4 + len(header) + len(codigo) # 4 = campo de tamanho

with open(arquivo_saida, 'wb') as f:
f.write(struct.pack('I', tamanho_total)) # Tamanho total
f.write(bytearray(header)) # Header
f.write(bytearray(codigo)) # Instruções

print(f"Programa compilado com sucesso: {arquivo_saida}")

if __name__ == "__main__":
montar_programa("programa.asm", "programa.bin")
49 changes: 49 additions & 0 deletions modular/controle.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// controle.c
#include "controle.h"
#include <stdio.h>

// ROM com microinstruções
microinstrucao Armazenamento[512];

// Microinstrução atual e contador de próxima instrução
microinstrucao MIR;
palavra MPC = 0;

// Campos extraídos da MIR
byte MIR_B, MIR_Operacao, MIR_Deslocador, MIR_MEM, MIR_pulo;
palavra MIR_C;

// Carrega o microprograma de controle da ROM (arquivo binário)
void carregar_microprograma() {
FILE* microprog = fopen("microprog.rom", "rb");

if (microprog != NULL) {
fread(Armazenamento, sizeof(microinstrucao), 512, microprog);
fclose(microprog);
} else {
printf("Erro: não foi possível abrir microprog.rom\n");
}
}

// Extrai os campos da microinstrução atual (MIR)
void decodificar_microinstrucao() {
MIR = Armazenamento[MPC];

MIR_B = (MIR) & 0b1111;
MIR_MEM = (MIR >> 4) & 0b111;
MIR_C = (MIR >> 7) & 0b111111111;
MIR_Operacao = (MIR >> 16) & 0b111111;
MIR_Deslocador = (MIR >> 22) & 0b11;
MIR_pulo = (MIR >> 24) & 0b111;
MPC = (MIR >> 27) & 0b111111111;
}

// Atualiza o MPC com base nas flags N, Z ou no valor de MBR
void pular() {
extern byte N, Z;
extern byte MBR;

if (MIR_pulo & 0b001) MPC = MPC | (N << 8);
if (MIR_pulo & 0b010) MPC = MPC | (Z << 8);
if (MIR_pulo & 0b100) MPC = MPC | MBR;
}
23 changes: 23 additions & 0 deletions modular/controle.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// controle.h
#ifndef CONTROLE_H
#define CONTROLE_H

#include "comuns.h"

// ROM de controle: 512 microinstruções
extern microinstrucao Armazenamento[512];

// Microinstrução atual e próximo contador
extern microinstrucao MIR;
extern palavra MPC;

// Funções principais do controle
void carregar_microprograma();
void decodificar_microinstrucao();
void pular();

// Campos decodificados da MIR
extern byte MIR_B, MIR_Operacao, MIR_Deslocador, MIR_MEM, MIR_pulo;
extern palavra MIR_C;

#endif
94 changes: 94 additions & 0 deletions modular/cpu.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
// cpu.c
#include "cpu.h"
#include "controle.h"
#include "memoria.h"

// Registradores
palavra SP = 0, LV = 0, TOS = 0;
palavra OPC = 0, CPP = 0, H = 0;

// Barramentos
palavra Barramento_B, Barramento_C;

// Flags da ALU
byte N = 0, Z = 0;

// Executa um ciclo de microinstrução completo
void executar_ciclo() {
decodificar_microinstrucao(); // Extrai os campos da MIR
atribuir_barramento_B(); // Define o valor no barramento B
realizar_operacao_ALU(); // Executa operação da ALU
atribuir_barramento_C(); // Escreve o resultado nos registradores
operar_memoria(); // Acessa memória se necessário
pular(); // Define a próxima microinstrução
}

// Define Barramento_B com base no campo MIR_B
void atribuir_barramento_B() {
switch (MIR_B) {
case 0: Barramento_B = MDR; break;
case 1: Barramento_B = PC; break;
case 2: // MBR com sinal (extensão de sinal)
Barramento_B = MBR;
if (MBR & 0x80)
Barramento_B |= 0xFFFFFF00;
break;
case 3: Barramento_B = MBR; break;
case 4: Barramento_B = SP; break;
case 5: Barramento_B = LV; break;
case 6: Barramento_B = CPP; break;
case 7: Barramento_B = TOS; break;
case 8: Barramento_B = OPC; break;
default: Barramento_B = 0xFFFFFFFF; break;
}
}

// Executa a operação da ALU e atualiza as flags
void realizar_operacao_ALU() {
switch (MIR_Operacao) {
case 12: Barramento_C = H & Barramento_B; break;
case 17: Barramento_C = 1; break;
case 18: Barramento_C = -1; break;
case 20: Barramento_C = Barramento_B; break;
case 24: Barramento_C = H; break;
case 26: Barramento_C = ~H; break;
case 28: Barramento_C = H | Barramento_B; break;
case 44: Barramento_C = ~Barramento_B; break;
case 53: Barramento_C = Barramento_B + 1; break;
case 54: Barramento_C = Barramento_B - 1; break;
case 57: Barramento_C = H + 1; break;
case 59: Barramento_C = -H; break;
case 60: Barramento_C = H + Barramento_B; break;
case 61: Barramento_C = H + Barramento_B + 1; break;
case 63: Barramento_C = Barramento_B - H; break;
default: Barramento_C = 0; break;
}

// Flags: Z = zero, N = não-zero
if (Barramento_C) {
N = 0;
Z = 1;
} else {
N = 1;
Z = 0;
}

// Deslocamentos
switch (MIR_Deslocador) {
case 1: Barramento_C <<= 8; break;
case 2: Barramento_C >>= 1; break;
}
}

// Atualiza registradores com base no campo MIR_C
void atribuir_barramento_C() {
if (MIR_C & 0b000000001) MAR = Barramento_C;
if (MIR_C & 0b000000010) MDR = Barramento_C;
if (MIR_C & 0b000000100) PC = Barramento_C;
if (MIR_C & 0b000001000) SP = Barramento_C;
if (MIR_C & 0b000010000) LV = Barramento_C;
if (MIR_C & 0b000100000) CPP = Barramento_C;
if (MIR_C & 0b001000000) TOS = Barramento_C;
if (MIR_C & 0b010000000) OPC = Barramento_C;
if (MIR_C & 0b100000000) H = Barramento_C;
}
25 changes: 25 additions & 0 deletions modular/cpu.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// cpu.h
#ifndef CPU_H
#define CPU_H

#include "comuns.h"

// Função principal do ciclo da CPU
void executar_ciclo();

// Barramento B: fonte de dados
void atribuir_barramento_B();

// ALU: executa operações entre H e B
void realizar_operacao_ALU();

// Barramento C: destino do resultado da ALU
void atribuir_barramento_C();

// Flags
extern byte N, Z;

// Registradores principais
extern palavra SP, LV, TOS, OPC, CPP, H;

#endif
49 changes: 49 additions & 0 deletions modular/gerar_microprog.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import struct

def instr(B=0, MEM=0, C=0, op=0, shift=0, jump=0, next_mpc=0):
valor = (
(next_mpc & 0x1FF) << 27 |
(jump & 0x7) << 24 |
(shift & 0x3) << 22 |
(op & 0x3F) << 16 |
(C & 0x1FF) << 7 |
(MEM & 0x7) << 4 |
(B & 0xF)
)
return valor

micro = [0] * 512

# FETCH
micro[0] = instr(C=0b000000100, B=2, next_mpc=1)
micro[1] = instr(MEM=0b001, next_mpc=2)
micro[2] = instr(C=0b000000100, B=2, op=53, next_mpc=3)
micro[3] = instr(jump=0b100, next_mpc=0)

# PUSH (0x01)
micro[4] = instr(C=0b000000001, B=2, next_mpc=5)
micro[5] = instr(MEM=0b001, next_mpc=6)
micro[6] = instr(C=0b000000100, B=2, op=53, next_mpc=7)
micro[7] = instr(C=0b000000010, B=2, next_mpc=8)
micro[8] = instr(C=0b000100000, B=4, next_mpc=9)
micro[9] = instr(C=0b000010000, B=4, op=53, next_mpc=10)
micro[10] = instr(C=0b000000001, B=5, next_mpc=11)
micro[11] = instr(MEM=0b100, next_mpc=12)
micro[12] = instr(C=0b001000000, B=2, next_mpc=13)
micro[13] = instr(next_mpc=0)

# ADD (0x02)
micro[14] = instr(C=0b100000000, B=7, next_mpc=15)
micro[15] = instr(C=0b000010000, B=4, op=54, next_mpc=16)
micro[16] = instr(C=0b000000001, B=4, next_mpc=17)
micro[17] = instr(MEM=0b010, next_mpc=18)
micro[18] = instr(C=0b001000000, B=2, op=60, next_mpc=19)
micro[19] = instr(next_mpc=0)

# PRINT (0x03)
micro[20] = instr(next_mpc=0)

with open("microprog.rom", "wb") as f:
f.write(struct.pack("Q" * len(micro), *micro))

print("microprog.rom gerado com sucesso!")
9 changes: 9 additions & 0 deletions modular/includes/comuns.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// includes/comuns.h
#ifndef COMUNS_H
#define COMUNS_H

typedef unsigned char byte; // 8 bits
typedef unsigned int palavra; // 32 bits
typedef unsigned long int microinstrucao; // 64 bits, usamos 36

#endif
Loading