1+ class CPU :
2+ def __init__ (self , barramento ):
3+ self .barramento = barramento
4+ self .pc = 0x00000000
5+ self .regs = [0 ] * 32
6+
7+ # Funcoes Auxiliares
8+ def correcao_dsinal (self , entrada ):
9+ entrada = entrada & 0xFFFFFFFF
10+ if (entrada & 0x80000000 ) == 0x80000000 :
11+ return entrada - 0x100000000
12+ return entrada
13+
14+ def correcao_dtamanho (self , entrada ):
15+ return entrada & 0xFFFFFFFF
16+
17+ def carregar_programa (self , lista_hex ):
18+ addr = 0
19+ for inst in lista_hex :
20+ self .barramento .escreva (addr , inst , 32 )
21+ addr += 4
22+
23+ # Execucao
24+ def run (self ):
25+ ciclos = 0
26+ while True :
27+ if not self .Decoder ():
28+ break
29+ ciclos += 1
30+ if ciclos > 5000 :
31+ print ("Aviso: Limite de ciclos atingido." )
32+ break
33+ self .barramento .imprimir ()
34+ print ("\n " )
35+ print ("CPU Halt (Fim do programa)." )
36+
37+ # Decodificador
38+ def Decoder (self ):
39+ self .regs [0 ] = 0
40+
41+ instrucao = self .barramento .leia (self .pc , 32 )
42+ if instrucao == 0 : return False
43+
44+ next_pc = self .pc + 4
45+
46+ # Separação da entrada
47+ opcode = instrucao & 0x7F
48+ rd = (instrucao >> 7 ) & 0x1F
49+ funct3 = (instrucao >> 12 ) & 0x7
50+ rs1 = (instrucao >> 15 ) & 0x1F
51+ rs2 = (instrucao >> 20 ) & 0x1F
52+ funct7 = (instrucao >> 25 ) & 0x7F
53+
54+ # Imediatos (Com correção de sinal ajustada)
55+ # Tipo I Imediato
56+ imm_i = instrucao >> 20
57+ if imm_i & 0x800 : imm_i -= 0x1000
58+ # Tipo S Imediato
59+ imm_s = ((instrucao >> 25 ) << 5 ) | ((instrucao >> 7 ) & 0x1F )
60+ if imm_s & 0x800 : imm_s -= 0x1000
61+ # Tipo B Imediato
62+ imm_b = ((instrucao >> 31 ) << 12 ) | ((instrucao & 0x7E000000 ) >> 20 ) | ((instrucao & 0xF00 ) >> 7 ) | ((instrucao & 0x80 ) << 4 )
63+ if imm_b & 0x1000 : imm_b -= 0x2000
64+ # Tipo U Imediato
65+ imm_u = instrucao & 0xFFFFF000
66+ # Tipo J Imediato
67+ imm_j = ((instrucao >> 31 ) << 20 ) | (instrucao & 0xFF000 ) | ((instrucao & 0x100000 ) >> 9 ) | ((instrucao & 0x7FE00000 ) >> 20 )
68+ if imm_j & 0x100000 : imm_j -= 0x200000
69+
70+ # Instrucoes - Em ordem de Opcode
71+
72+ # Opcode 0b0000011 - Tipo I (LOAD)
73+ if opcode == 0x03 :
74+ addr = self .regs [rs1 ] + imm_i
75+
76+ if funct3 == 0x0 : # LB (Load Byte)
77+ val = self .barramento .leia (addr , 8 )
78+ if (val & 0x80 ) != 0 :
79+ val -= 0x100
80+ self .regs [rd ] = self .correcao_dtamanho (val )
81+
82+ elif funct3 == 0x1 : # LH (Load Half - Signed)
83+ val = self .barramento .leia (addr , 16 )
84+ if (val & 0x8000 ) != 0 :
85+ val -= 0x10000
86+ self .regs [rd ] = self .correcao_dtamanho (val )
87+
88+ elif funct3 == 0x2 : # LW (Load Word)
89+ self .regs [rd ] = self .barramento .leia (addr , 32 )
90+
91+ elif funct3 == 0x4 : # LBU (Load Byte Unsigned)
92+ self .regs [rd ] = self .barramento .leia (addr , 8 )
93+
94+ elif funct3 == 0x5 : # LHU (Load Half Unsigned)
95+ self .regs [rd ] = self .barramento .leia (addr , 16 )
96+
97+ # Opcode 0b0010011 - Tipo I (OPERACAO IMEDIATA)
98+ elif opcode == 0x13 :
99+ val1 = self .correcao_dsinal (self .regs [rs1 ]) # Valor com sinal
100+
101+ if funct3 == 0x0 : # ADDI
102+ self .regs [rd ] = self .correcao_dtamanho (val1 + imm_i )
103+
104+ elif funct3 == 0x1 : # SLLI
105+ self .regs [rd ] = self .correcao_dtamanho (val1 << (imm_i & 0x1F ))
106+
107+ elif funct3 == 0x2 : # SLTI (Set Less Than Immediate - Signed)
108+ self .regs [rd ] = 1 if val1 < imm_i else 0
109+
110+ elif funct3 == 0x3 : # SLTIU (Set Less Than Immediate Unsigned)
111+ if self .correcao_dtamanho (val1 ) < self .correcao_dtamanho (imm_i ):
112+ self .regs [rd ] = 1
113+ else :
114+ self .regs [rd ] = 0
115+
116+ elif funct3 == 0x4 : # XORI
117+ self .regs [rd ] = self .correcao_dtamanho (val1 ^ imm_i )
118+
119+ elif funct3 == 0x5 : # SRLI / SRAI
120+ shamt = imm_i & 0x1F
121+ if (imm_i >> 10 ) & 1 : # SRAI (Shift Right Arithmetic)
122+ self .regs [rd ] = self .correcao_dtamanho (val1 >> shamt )
123+ else : # SRLI (Shift Right Logical)
124+ self .regs [rd ] = self .correcao_dtamanho (self .regs [rs1 ] >> shamt )
125+
126+ elif funct3 == 0x6 : # ORI
127+ self .regs [rd ] = self .correcao_dtamanho (val1 | imm_i )
128+
129+ elif funct3 == 0x7 : # ANDI
130+ self .regs [rd ] = self .correcao_dtamanho (val1 & imm_i )
131+
132+ # Opcode 0b0010111 - Tipo U (CRIAR ENDERECO IMEDIATO)
133+ elif opcode == 0x17 : # AUIPC (add upper immediate to PC)
134+ self .regs [rd ] = self .correcao_dtamanho (self .pc + imm_u )
135+
136+ # Opcode 0b0100011 - S-Type (ARMAZENAR)
137+ elif opcode == 0x23 :
138+ addr = self .regs [rs1 ] + imm_s
139+ if funct3 == 0x0 : # SB (Store Byte)
140+ self .barramento .escreva (addr , self .regs [rs2 ] & 0xFF , 8 )
141+ elif funct3 == 0x1 : # SH (store half)
142+ self .barramento .escreva (addr , self .regs [rs2 ] & 0xFFFF , 16 )
143+ elif funct3 == 0x2 : # SW (Store Word)
144+ self .barramento .escreva (addr , self .regs [rs2 ], 32 )
145+
146+ # Opcode 0b0110011 - Tipo R (OPERACOES ENTRE REGISTRADORES)
147+ elif opcode == 0x33 :
148+ val1 = self .correcao_dsinal (self .regs [rs1 ])
149+ val2 = self .correcao_dsinal (self .regs [rs2 ])
150+
151+ if funct3 == 0x0 :
152+ if funct7 == 0x00 : # ADD
153+ self .regs [rd ] = self .correcao_dtamanho (val1 + val2 )
154+ elif funct7 == 0x20 : # SUB
155+ self .regs [rd ] = self .correcao_dtamanho (val1 - val2 )
156+
157+ elif funct3 == 0x1 : # SLL (Shift Left Logical)
158+ shamt = val2 & 0x1F
159+ self .regs [rd ] = self .correcao_dtamanho (val1 << shamt )
160+
161+ elif funct3 == 0x2 : # SLT (Set Less Than Signed)
162+ self .regs [rd ] = 1 if val1 < val2 else 0
163+
164+ elif funct3 == 0x3 : # SLTU (Set Less Than Unsigned)
165+ u_val1 = self .correcao_dtamanho (val1 )
166+ u_val2 = self .correcao_dtamanho (val2 )
167+ self .regs [rd ] = 1 if u_val1 < u_val2 else 0
168+
169+ elif funct3 == 0x4 : # XOR
170+ self .regs [rd ] = self .correcao_dtamanho (val1 ^ val2 )
171+
172+ elif funct3 == 0x5 : # SRL / SRA (Shift Right)
173+ shamt = val2 & 0x1F
174+ if funct7 == 0x20 : # SRA (Arithmetic)
175+ self .regs [rd ] = self .correcao_dtamanho (val1 >> shamt )
176+ else : # SRL (Logical)
177+ self .regs [rd ] = self .correcao_dtamanho (self .correcao_dtamanho (val1 ) >> shamt )
178+
179+ elif funct3 == 0x6 : # OR
180+ self .regs [rd ] = self .correcao_dtamanho (val1 | val2 )
181+
182+ elif funct3 == 0x7 : # AND
183+ self .regs [rd ] = self .correcao_dtamanho (val1 & val2 )
184+
185+ # Opcode 0b0110111 - Tipo U (CARREGAR ENDERECO IMEDIATO)
186+ elif opcode == 0x37 : # LUI
187+ self .regs [rd ] = imm_u
188+
189+ # Opcode 0x1100011 - Tipo B (ESCOLHAS)
190+ elif opcode == 0x63 : # BRANCH
191+ val1 = self .correcao_dsinal (self .regs [rs1 ])
192+ val2 = self .correcao_dsinal (self .regs [rs2 ])
193+ desvio = False
194+
195+ # Comparações com SINAL (Tratam -1 como menor que 1)
196+ if funct3 == 0x0 : # BEQ (IGUAL)
197+ desvio = (val1 == val2 )
198+ elif funct3 == 0x1 : # BNE (DIFERENTE)
199+ desvio = (val1 != val2 )
200+ elif funct3 == 0x4 : # BLT (MENOR QUE)
201+ desvio = (val1 < val2 )
202+ elif funct3 == 0x5 : # BGE (MAIOR OU IGUAL)
203+ desvio = (val1 >= val2 )
204+ elif funct3 == 0x6 : # BLTU (MAIIOR)
205+ desvio = (self .correcao_dtamanho (val1 ) < self .correcao_dtamanho (val2 ))
206+ elif funct3 == 0x7 : # BGEU (MENOR OU IGUAL)
207+ desvio = (self .correcao_dtamanho (val1 )>= self .correcao_dtamanho (val2 ))
208+
209+ # Se a condição for verdadeira, atualiza o next_pc
210+ if desvio == True :
211+ next_pc = self .pc + imm_b
212+
213+ # Opcode 0x67 (1100111) - Tipo I (PULO com registrador)
214+ elif opcode == 0x67 : # JALR
215+ self .regs [rd ] = next_pc
216+ next_pc = (self .regs [rs1 ] + imm_i ) & ~ 1
217+
218+ # Opcode 0x6F (1101111) - Tipo J (PULO)
219+ elif opcode == 0x6F : # JAL
220+ self .regs [rd ] = next_pc
221+ next_pc = self .pc + imm_j
222+
223+ self .pc = self .correcao_dtamanho (next_pc )
224+ return True
0 commit comments