flowchart TB
subgraph CONC["Fundamentos conceituais"]
AO["Arquitetura × Organização"]
HIST["5 gerações<br/>RISC × CISC"]
VN["Von Neumann"]
HV["Harvard / Harvard mod."]
end
subgraph CASO["Estudo de caso e métricas"]
PIC["PIC18F4550<br/>(blocos, ciclo, pipeline)"]
MET["Métricas:<br/>T = N·CPI·Tcy<br/>IPC, MIPS, Amdahl, Gustafson"]
end
subgraph PRAT["Prática (Projeto Integrador)"]
T1["Tarefa 1<br/>Ambiente + LED"]
T2["Tarefa 2<br/>Quadro Arq/Org<br/>Harvard mod no .map"]
T3["Tarefa 3<br/>Medição de tempo<br/>no osciloscópio"]
end
CONC --> CASO --> PRAT
PRAT --> M2["Módulo 02:<br/>Representação de Dados"]
Módulo 1: Fundamentos de Arquitetura e Organização de Computadores — Resumo
Olha só: dois Intel x86, mesmo binário, e um termina cinco vezes antes do outro. Mesma arquitetura, desempenhos completamente diferentes. Por quê? A resposta cabe em duas palavras que a literatura técnica mistura — arquitetura e organização — e que neste módulo a gente separa de vez.
Arquitetura e Organização
Vou direto. Arquitetura é o que você, programador, enxerga do hardware: instruções, registradores nomeáveis, modos de endereçamento, modelo de memória, mecanismos de exceção, E/S. É um contrato público — o fabricante diz “estas instruções existem e fazem isso”, e seu código depende disso. Organização é como o fabricante implementou o cardápio por dentro: pipeline, caches, frequência, larguras de barramento, tecnologia das memórias. Duas organizações diferentes podem implementar a mesma arquitetura — foi assim que a IBM montou o System/360 em 1964, com modelos baratos e caríssimos rodando o mesmo programa.
flowchart TB
P["Programador<br/>(código C, ASM)"]
A["Arquitetura<br/>ISA, registradores, modelo de memória,<br/>modos de endereçamento, exceções"]
O["Organização<br/>Pipeline, caches, ULA, barramentos,<br/>frequência, tecnologia de memória"]
H["Silício<br/>Transistores, geometria, materiais"]
P -->|"escreve programa"| A
A -.->|"contrato visível"| P
A --> O
O --> H
H -.->|"desempenho percebido"| P
Tem um truque que eu chamo de prova do programador e ele resolve quase tudo: se você muda um detalhe e o resultado lógico de algum programa correto muda junto, é arquitetura; se só muda tempo, consumo ou custo, é organização. Olha o Core i9-13900K e o i3-13100: os dois são x86-64, o binário roda nos dois. Arquiteturalmente, irmãos. Por dentro, o i9 tem mais núcleos, mais cache, clock maior, pipeline maior. Organizações em outro planeta. Aí está a resposta da abertura.
Pensa rápido: se eu trocar a SRAM de 2 KB do PIC18F4550 por uma de 8 KB sem mexer no mapa de endereçamento visível ao programador, isso muda arquitetura ou organização? Aplica a prova do programador.
E ainda tem a microarquitetura, dentro da organização, descrevendo como o processador implementa internamente a arquitetura — pipeline, execução fora de ordem, unidade de controle. Cuidado com o marketing: “arquitetura Skylake” ou “arquitetura M2” são, no rigor que a gente adota, microarquiteturas dentro das famílias x86-64 e ARMv8-A. Voltam nos Módulos 04 e 05.
Gerações e a Briga RISC versus CISC
Por que história numa disciplina técnica? Porque cada inovação arquitetural respondeu a uma limitação tecnológica concreta — e entender a limitação é o jeito de entender por que a decisão foi tomada daquele jeito.
timeline
title Cinco gerações de computadores
1940-1955 : 1ª geração<br/>Válvulas termiônicas<br/>ENIAC, EDVAC<br/>programa armazenado
1955-1965 : 2ª geração<br/>Transistor discreto<br/>IBM 7090, PDP-1<br/>FORTRAN, COBOL
1965-1971 : 3ª geração<br/>CI SSI e MSI<br/>IBM System/360<br/>família arquitetural
1971-1980 : 4ª geração<br/>Microprocessador<br/>Intel 4004, 8086<br/>computador pessoal
1980-hoje : 5ª geração<br/>VLSI, computação ubíqua<br/>x86, ARM, PIC18<br/>RISC × CISC
A primeira geração (1940–1955) é a das válvulas: o ENIAC era programado por reconexão de cabos, e foi em 1945 que von Neumann formulou no EDVAC o programa armazenado. A segunda trouxe transistores discretos, FORTRAN e COBOL. A terceira (1960–1970) trouxe circuitos integrados, o System/360 e a microprogramação. A quarta começou em 1971 com o Intel 4004 e viabilizou o PC. A quinta, dos anos 1980 em diante, é a do VLSI e da computação ubíqua. O PIC18F4550 da sua mesa, projetado por volta de 2007, é típico da quinta — mas executa internamente um modelo conceitual de 1945. A história do nosso campo é cumulativa.
A briga RISC versus CISC vale uma nota. CISC (VAX-11, x86) apostou em conjuntos enormes para reduzir o trabalho do compilador. Patterson e Hennessy perceberam que os compiladores só usavam um subconjunto pequeno e propuseram o contrário: poucas instruções simples, tamanho fixo, um ciclo cada, memória só via load/store. O PIC18F4550 é híbrido — instrução de 16 bits de tamanho fixo (RISC), mas 75 instruções com várias misturando memória e aritmética como ADDWF (CISC). Desfecho pragmático: x86 modernos traduzem para micro-operações RISC, e ARM/RISC-V acumularam extensões que os aproximaram do CISC.
Von Neumann e a Harvard Modificada do PIC
A invenção que justifica o nome é brutal: instruções são números, ficam na mesma memória dos dados, lidas do mesmo jeito. Antes do EDVAC, programar era religar cabos por horas; com programa armazenado, programa virou dado, e isso destrava compiladores e sistemas operacionais. O modelo tem cinco subsistemas — unidade de controle, ULA, registradores, memória principal e E/S — e roda o ciclo de busca-decodificação-execução: o PC aponta a próxima instrução, a memória devolve, o IR recebe e decodifica, e o PC é incrementado ou alterado por desvio.
flowchart LR
subgraph CPU["CPU"]
UC["Unidade<br/>de Controle"]
ULA["ULA"]
REG["Registradores<br/>PC, IR, ACC"]
end
MEM["Memória Principal<br/>instruções + dados<br/>(mesma)"]
IO["Subsistema<br/>de E/S"]
CPU <-->|"barramento único<br/>endereço/dado/controle"| MEM
CPU <--> IO
Tem uma pegadinha: instrução e dado dividem o mesmo barramento, então a CPU não busca uma instrução e lê um dado no mesmo instante. Backus, no Turing de 1977, batizou isso de gargalo de Von Neumann:
\tau \geq \tau_p + 2\,\tau_m,
porque cada instrução exige buscar a instrução e mais um acesso ao dado. Quando \tau_m engole \tau_p — situação que virou regra — a CPU passa a maior parte do tempo esperando. É a memory wall. Em CPU de propósito geral, a saída foi a hierarquia de caches do Módulo 09. Em microcontrolador, foi outra: trocar o modelo.
A Harvard mantém instruções e dados em memórias fisicamente separadas, cada uma com seu barramento. O nome vem do Mark I de Howard Aiken, de 1944. Num mesmo ciclo, o processador busca uma instrução e lê ou escreve um dado, sem briga. No PIC18 as larguras diferem — instrução tem 16 bits, dado tem 8 — e as tecnologias também: Flash para instrução, SRAM para dado. Daí sai, em regime permanente, uma instrução por ciclo de máquina sem cache.
Mas a Harvard pura tem um problema: tabelas e constantes grandes não cabem na RAM, e ocupariam RAM mesmo sendo imutáveis. Desastre num embarcado. A Harvard modificada do PIC18 resolve com instruções específicas que leem bytes da memória de instruções como se fossem dados: TBLRD*, TBLRD*+, TBLRD*- e TBLRD+*, via ponteiro TBLPTR com retorno em TABLAT. Na prática, ao declarar static const uint8_t tabela[] = {...} em C, o XC8 aloca em Flash e emite essa sequência sozinho.
flowchart LR
MI["Memória de<br/>Instruções<br/>(Flash 32 KB)"]
CPU["CPU"]
MD["Memória de<br/>Dados<br/>(SRAM 2 KB)"]
EE["EEPROM<br/>256 bytes"]
MI -->|"barramento de<br/>instruções 16 bits"| CPU
CPU <-->|"barramento de<br/>dados 8 bits"| MD
MI -.->|"TBLRD via TBLPTR<br/>(Harvard modificada)"| CPU
CPU <-.->|"EECON1/EECON2<br/>(protocolo)"| EE
Tem ainda um terceiro espaço no PIC18: a EEPROM de 256 bytes para dados que sobrevivem ao desligamento, acessada por EECON1/EECON2. Curiosidade: o x86 moderno, para o programador, é Von Neumann — uma memória só. Mas as caches L1 dele são separadas em instrução e dado, organização de inspiração harvardiana. Arquitetura Von Neumann, organização mista — a prova do programador resolve o paradoxo numa frase.
O PIC18F4550 como Estudo de Caso
Por que esse chip? Regularidade ortogonal (75 instruções, quase todas de um ciclo, codificação fixa de 16 bits) que permite estudar a ISA inteira em um módulo; periféricos integrados (ADC, USB, UART, SPI, I²C, comparadores, timers) no mesmo datasheet; timing previsível, sem cache nem execução fora de ordem, com tempo de execução calculável no papel; e o KIT ACEPIC PRO V8.2, barato e robusto.
flowchart TB
subgraph Nucleo["Núcleo do PIC18F4550"]
UC["Unidade<br/>de Controle"]
ULA["ULA 8 bits"]
W["WREG"]
ST["STATUS<br/>C, DC, Z, OV, N"]
end
Flash["Flash 32 KB<br/>(16 K palavras<br/>de 16 bits)"]
SRAM["SRAM 2 KB<br/>(16 bancos +<br/>Access Bank)"]
EE["EEPROM<br/>256 bytes"]
subgraph Perif["Periféricos integrados"]
USB["USB 2.0"]
UART["EUSART"]
MSSP["MSSP<br/>(I²C/SPI)"]
ADC["ADC 10 bits<br/>13 canais"]
TIM["Timers<br/>+ CCP/PWM"]
IO["35 pinos I/O<br/>PORTA..PORTE"]
end
CK["Oscilador externo<br/>8 MHz → ÷4 → Fcy = 2 MHz<br/>+ PLL para USB"]
Flash --> Nucleo
Nucleo <--> SRAM
Nucleo <-.-> EE
Nucleo <--> Perif
CK --> Nucleo
A CPU traz unidade de controle, ULA de 8 bits, WREG e STATUS com cinco flags (Carry, Digit Carry, Zero, Overflow, Negative). A Flash de 32 KB guarda 16 K palavras de 16 bits, reprogramável in-circuit. A SRAM de 2 KB se organiza em 16 bancos via BSR, com o Access Bank combinando 96 bytes da RAM e 160 bytes de SFRs. Os periféricos: dois MSSP, EUSART, USB 2.0 full-speed, ADC de 10 bits, três comparadores, quatro timers, dois CCP e 35 pinos de I/O.
Aplica a prova do programador — é a base da Tarefa 3 do Projeto Integrador. As 75 instruções, o WREG, os flags, os três espaços de memória, SFRs como TRISx, LATx e ADCONx são arquitetura. Já o pipeline de dois estágios, o Access Bank, a largura física do barramento, o cristal externo, a divisão por quatro, a PLL do USB são organização. Trocar a SRAM por uma mais rápida muda só tempo.
O ciclo de instrução compacta as cinco fases conceituais em dois estágios físicos, fetch e execute, porque a Harvard permite buscar a próxima instrução enquanto a atual executa. Após a latência inicial de um ciclo, conclui-se uma instrução por ciclo de máquina. A exceção são as que mexem no PC — GOTO, CALL, BRA tomado, RETURN, RETFIE, BTFSS/BTFSC causando skip. Nessas, o prefetch trouxe a instrução errada e é descartado, e o CPI vira 2. Decora, porque cai.
Métricas de Desempenho
Quando alguém te disser que um processador é “duas vezes mais rápido”, devolve a pergunta: em qual carga, qual compilador, qual frequência, medindo o quê? Sem isso, “mais rápido” é palavra vazia. A equação central da disciplina é:
T = N_{\text{instr}} \cdot \text{CPI} \cdot T_{cy}.
Cada fator depende de uma camada: N_{\text{instr}} depende do algoritmo e do compilador; CPI depende da arquitetura, da microarquitetura e da mistura de instruções; T_{cy} depende exclusivamente da organização. Otimizar é atacar os três ao mesmo tempo.
flowchart LR
XT["Cristal externo<br/>Fosc = 8 MHz"]
DIV["Divisor<br/>÷ 4"]
FCY["Clock de máquina<br/>Fcy = 2 MHz<br/>Tcy = 500 ns"]
CPU["CPU<br/>(Q1, Q2, Q3, Q4)"]
XT --> DIV --> FCY --> CPU
Detalhe do PIC18 que cai em prova: o cristal externo gera F_{osc}, mas um divisor por quatro produz o clock de máquina F_{cy} = F_{osc}/4. Para o cristal de 8 MHz do KIT, F_{cy} = 2 MHz e T_{cy} = 500 ns. Trocar F_{osc} por F_{cy} é o erro mais frequente da disciplina e dá previsão quatro vezes menor que a medida. Para uma mistura com frequências f_i e CPIs c_i,
\text{CPI}_{\text{médio}} = \sum_i f_i \, c_i.
Um programa com 90% de instruções de CPI 1 e 10% de desvios tomados (CPI 2) tem CPI médio 1,10; a 8 MHz, com 10 000 instruções, dá 5,5 ms. O conceito gêmeo é o throughput: IPC = 1/\text{CPI}, e no PIC18, em pipeline cheio, fica próximo de 1. Superescalares chegam a IPC maior que 1 — Módulo 15. Pra tornar o efeito palpável, um pulso em RD0 delimitando um laço de soma — padrão que volta nas tarefas do Projeto Integrador.
A Lei de Amdahl é a lição quantitativa mais importante daqui. Pergunta natural: se você acelera uma fração f do tempo por um fator k, qual o ganho global? Gene Amdahl, 1967, respondeu assim:
S = \frac{1}{(1-f) + \dfrac{f}{k}}.
flowchart LR
T0["Tempo original<br/>T = 1"]
F["Fração f<br/>acelerável"]
NF["Fração (1−f)<br/>inalterada"]
K["Aceleração<br/>por fator k"]
S["Speedup global<br/>S = 1 / ((1−f) + f/k)"]
LIM["Limite k → ∞<br/>S_max = 1 / (1−f)"]
T0 --> F
T0 --> NF
F --> K
K --> S
NF --> S
S --> LIM
No limite k \to \infty, o teto é S_{\max} = 1/(1-f). Lê de novo: acelerar infinitamente 90% do tempo dá speedup de apenas dez vezes, porque os 10% restantes seguem consumindo o mesmo absoluto. Acelerar por dez uma fração de 50% dá 1,82, não 5,5. Na prática, otimização vale a pena onde o programa gasta tempo, e o ganho global tem teto na fração não otimizada. Antes de otimizar, pergunta: que fração do tempo essa rotina consome?
A Lei de Gustafson (1988) é o contraponto: quando o problema cresce com os recursos, o speedup escalado vale (1-f) + k\cdot f, sem o teto rígido. Amdahl é strong scaling; Gustafson, weak scaling. Em embarcado, o problema é dado pela aplicação, então Amdahl pesa mais. Em data center, Gustafson.
Se um programa gasta 30% do tempo em E/S sequencial obrigatória e 70% em laço puramente computacional, qual o speedup máximo teórico mesmo paralelizando o laço infinitamente? Faz a conta agora. É exatamente o tipo de pergunta que cai na prova.
Da Teoria ao Kit: o Projeto Integrador do Módulo
A cadeia que conecta seu código C ao silício tem cinco blocos: MPLAB X IDE; XC8 traduzindo C em código de máquina; pic-as fazendo o mesmo a partir de assembly puro; arquivo .hex no formato Intel HEX; gravação via bootloader (AN1310 ou ACEPIC Terminal pela USB) ou via PICkit no header ICSP. Cada elo é candidato a travar.
flowchart LR
SRC["Código-fonte<br/>(.c / .asm)<br/>MPLAB X IDE"]
XC8["XC8 (C)<br/>ou pic-as (ASM)"]
LINK["Linker<br/>(.elf)"]
HEX["Imagem<br/>Intel HEX (.hex)"]
CHIP["PIC18F4550<br/>(Flash gravada)"]
SRC --> XC8 --> LINK --> HEX
HEX -->|"bootloader<br/>via USB"| CHIP
HEX -->|"PICkit<br/>via ICSP"| CHIP
A primeira tarefa é pôr a cadeia em pé e gravar um programa que pisca os oito LEDs em sequência — PORTD como saída, 500 ms entre acionamentos. O programa é trivial; o aprendizado está no entorno: driver CH340G, MPLAB X compatível, XC8 reconhecendo o PIC18F4550, jumpers no lugar, bootloader íntegro. Quatro pontos do kit comem aula quando ignorados: jumper LEDS fechado (senão L1–L8 não acende); jumper J1 na posição 1-2 alimentando o chip com 5 V; jumpers JP14 do cristal de 8 MHz fechados na vertical (senão o chip cai no oscilador interno e o programa parece rodar em frequência errada); DIP-switch DP2 com chaves 5 a 8 em OFF, que controlam cátodos de displays compartilhados com PORTD.
A segunda tarefa pede evidência empírica da Harvard modificada. Você grava um programa que define uma tabela de oito padrões em const uint8_t (Flash) e um índice em RAM; a cada iteração, o byte é lido via TBLRD e escrito em LATD. O entregável traz o quadro Arq/Org do PIC18F4550 e a inspeção do .map, onde padroes[] aparece em endereços baixos (Flash, a partir de 0x000000) e o índice em outra faixa (RAM, no Access Bank). A separação conceitual vira dois conjuntos disjuntos de endereços.
A terceira tarefa fecha o ciclo teoria-medição. Você eleva RD0 antes de um trecho instrumentado, abaixa depois, mede o pulso no osciloscópio e compara com o tempo teórico pela contagem de instruções. O entregável traz tabela de instruções, cálculo teórico, valor medido, erro relativo e fontes de incerteza. Aqui você age como engenheiro: prevê, mede, confronta. E lembra do diário de projeto em /docs/diario/ — pesa na avaliação contínua.
Síntese
Você saiu de uma distinção aparentemente acadêmica — arquitetura versus organização — e desembocou na configuração física de um microcontrolador real, com pulso medido no osciloscópio. A pergunta da abertura, sobre os dois Intel diferindo cinco vezes, tem resposta precisa: arquitetura define o contrato com o programador, organização define o desempenho real. Faz um teste rápido: enuncia arquitetura e organização e aplica a prova do programador; descreve o ciclo de busca-decodificação-execução; identifica o gargalo de Von Neumann; diferencia Harvard pura de modificada; calcula T = N_{\text{instr}} \cdot \text{CPI} \cdot T_{cy} sem esquecer da divisão por quatro do clock; aplica Amdahl. Se travar, volta no Módulo 1. No Módulo 2 vamos para representação de dados e aritmética. Provocação: por que somar dois números de 16 bits num chip de 8 bits exige mais de uma instrução, e qual registrador especial entra em cena na segunda?
Antes da próxima aula, abre o MPLAB X, compila o pisca-LED da Tarefa 1, conecta o osciloscópio em RD0 e mede a largura do pulso. Compara com o valor que você calcular pela contagem de instruções e pela relação T_{cy} = 4/F_{osc}. O encontro entre teoria e medição é o ponto de partida do seu trabalho no semestre inteiro.