ccufcg / oac24.1

OAC 2024.1
GNU General Public License v3.0
1 stars 0 forks source link

GRUPO 03 #3

Open nobregat opened 1 month ago

DeboraSabrinaOPereira commented 1 month ago

Código em assembly com loops, condicionais e operações aritméticas ( arquivo .asm)

Não tem como adicionar um arquivo .asm, então segue abaixo em assembly:

O código se trata de um "fatorial", porém como a operação mul não faz parte das operações solicitadas, então o código foi alterado. Onde havia mul tem o add!

addi x1, x0, 5 #atribui 5 ao registrador x1 addi x2, x0, 1 #atribui 1 ao registrador x2 loop: #loop enquanto o registrador x1 for maior que x0 beq x1, x0, fim #sai do loop se x1 = x0 add x2, x2, x1 #soma x2 com x1 addi x1, x1, -1 #subtrai 1 de x1 para poder sair do loop quando chegar em 0 jal x0, loop #salta para o início do loop fim: #programa encerra quando x1 = x0 nop

DeboraSabrinaOPereira commented 1 month ago

Arquivo com as instruções binárias no formato RISC-V, de acordo com a especificação do pdf

fatorial.txt

Explicação da saída:

Cada instrução tem um formato padrão e instruções do tipo I, J e B organizam o imm em intervalos, logo a saída tem o número ou salto do rótulo organizado em intervalos específicos da instrução. Caso o imediato ou o salto sejam negativos, esse número é convertido para complemento de dois e organizado na estrutura da instrução correspondente, seguindo os intervalos.

def typeR(operandos, code, fun3, fun7): rd, rs1, rs2 = filtra_registradores("r", operandos) return f"0b{fun7}{rs2}{rs1}{fun3}{rd}{code}"

def typeI(operandos, code, fun3): rd, rs1, imd = filtra_registradores("i", operandos) return f"0b{imd}{rs1}{fun3}{rd}{code}"

def typeB(operandos, code, func3): rs1, rs2, imd = filtra_registradores("b", operandos)

offset11 = imd[1]
offset4_1 = imd[8:]
offset10_5 = imd[2:8]
offset12 = imd[0]

return f"0b{offset12}{offset10_5}{rs2}{rs1}{func3}{offset4_1}{offset11}{code}"

def typeJ(operandos, code): rd, imd = filtra_registradores("j", operandos)

offset19_12 = imd[1:9]
offset11 = imd[9]
offset10_1 = imd[10:]
offset20 = imd[0]

return f"0b{offset20}{offset10_1}{offset11}{offset19_12}{rd}{code}"

Ánalise do código por partes:

0b000000000101(imm) 00000(rs1) 000(fun3) 00001(rd) 0010011(opcode)

0b000000000001(imm) 00000(rs1) 000(fun3) 00010(rd) 0010011(opcode)

0b0(imm12) 000000(imm10_5) 00000(rs2) 00001(rs1) 000(fun3) 0100(imm4_1) 0(imm11) 1100011(opcode)

0b0000000(fun7) 00001(rs1) 00010(rs1) 000(fun3) 00010(rd) 0110011(opcode)

0b111111111111(imm) 00001(rs1) 000(fun3) 00001(rd) 0010011(opcode) na saída acima o imm está em complemento de dois

0b1(imm20) 1111111101(imm10_1) 1(imm11) 11111111(imm19_12) 00000(rd) 1101111(opcode) na saída acima o imm está em complemento de dois e dividido de acordo com a estrutura j-type Está em complemento de dois pois o salto foi calculado com (posição do rótulo - posição de onde está chamando o rótulo), resultando em um valor negativo

0b00000000000000000000000000010011(nop)

CarlosArturr commented 1 month ago

Exemplo de Execução do Simulador

pc = 0, opCode = 0010011, Register r1 = 5 pc = 1, opCode = 0010011, Register r2 = 1 pc = 2, opCode = 1100011, Register r0 = 0 pc = 3, opCode = 0110011, Register r2 = 6 pc = 4, opCode = 0010011, Register r1 = 4 pc = 5, opCode = 1101111, Register r0 = 0 loop //ilustrativo não implementado pc = 2, opCode = 1100011, Register r0 = 0 pc = 3, opCode = 0110011, Register r2 = 10 pc = 4, opCode = 0010011, Register r1 = 3 pc = 5, opCode = 1101111, Register r0 = 0 loop //ilustrativo pc = 2, opCode = 1100011, Register r0 = 0 pc = 3, opCode = 0110011, Register r2 = 13 pc = 4, opCode = 0010011, Register r1 = 2 pc = 5, opCode = 1101111, Register r0 = 0 loop //ilustrativo pc = 2, opCode = 1100011, Register r0 = 0 pc = 3, opCode = 0110011, Register r2 = 15 pc = 4, opCode = 0010011, Register r1 = 1 pc = 5, opCode = 1101111, Register r0 = 0 loop //ilustrativo pc = 2, opCode = 1100011, Register r0 = 0 pc = 3, opCode = 0110011, Register r2 = 16 pc = 4, opCode = 0010011, Register r1 = 0 pc = 5, opCode = 1101111, Register r0 = 0 loop //ilustrativo pc = 2, opCode = 1100011, Register r0 = 0 fim //ilustrativo pc = 6, opCode = 0010011, Register r0 = 0

PC final: 6 Registradores: [0, 0, 16, 0, 0, 0, 0, 0] Memoria: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

josetruta commented 1 month ago

Comportamento bastante semelhante ao que acontece em meu simulador, tanto nas instruções binárias, quanto na execução do simulador. Apenas tive que trocar a instrução que subtrai 1 do valor do registrador, pois meu simulador não está trabalhando em complemento de 2 - que também foi a principal diferença o nosso binário e o de vocês. Irei tentar implementar complemento de 2 no decorrer deste fim de semana e testar novamente.

joaopedro1422 commented 1 month ago

No nosso simulador o resultado da operação deu o mesmo (16) Simulação: 💻 Iniciando a simulação RISC-V 💻

═════════════════════════════════════════════════════════════════

📝 Executando instrução na posição PC=0 📥 Imediato lido: 5 (binário: 000000000101) 🧮 Executando ADDI: rd=1, rs1=0, imm=5, resultado=5 📝 Executando instrução na posição PC=1 📥 Imediato lido: 1 (binário: 000000000001) 🧮 Executando ADDI: rd=2, rs1=0, imm=1, resultado=1 📝 Executando instrução na posição PC=2 📥 Imediato lido: 4 (binário: 000000000100) 📝 Executando instrução na posição PC=3 📥 Imediato lido: 1 (binário: 000000000001) ➕ Executando ADD: rd=2, rs1=2, rs2=1, resultado=6 📝 Executando instrução na posição PC=4 📥 Imediato lido: -1 (binário: 111111111111) 🧮 Executando ADDI: rd=1, rs1=1, imm=-1, resultado=4 📝 Executando instrução na posição PC=5 📥 Imediato lido: 0 (binário: 000000000000) 🏃 Executando JAL: salto para PC=3 📝 Executando instrução na posição PC=2 📥 Imediato lido: 4 (binário: 000000000100) 📝 Executando instrução na posição PC=3 📥 Imediato lido: 1 (binário: 000000000001) ➕ Executando ADD: rd=2, rs1=2, rs2=1, resultado=10 📝 Executando instrução na posição PC=4 📥 Imediato lido: -1 (binário: 111111111111) 🧮 Executando ADDI: rd=1, rs1=1, imm=-1, resultado=3 📝 Executando instrução na posição PC=5 📥 Imediato lido: 0 (binário: 000000000000) 🏃 Executando JAL: salto para PC=3 📝 Executando instrução na posição PC=2 📥 Imediato lido: 4 (binário: 000000000100) 📝 Executando instrução na posição PC=3 📥 Imediato lido: 1 (binário: 000000000001) ➕ Executando ADD: rd=2, rs1=2, rs2=1, resultado=13 📝 Executando instrução na posição PC=4 📥 Imediato lido: -1 (binário: 111111111111) 🧮 Executando ADDI: rd=1, rs1=1, imm=-1, resultado=2 📝 Executando instrução na posição PC=5 📥 Imediato lido: 0 (binário: 000000000000) 🏃 Executando JAL: salto para PC=3 📝 Executando instrução na posição PC=2 📥 Imediato lido: 4 (binário: 000000000100) 📝 Executando instrução na posição PC=3 📥 Imediato lido: 1 (binário: 000000000001) ➕ Executando ADD: rd=2, rs1=2, rs2=1, resultado=15 📝 Executando instrução na posição PC=4 📥 Imediato lido: -1 (binário: 111111111111) 🧮 Executando ADDI: rd=1, rs1=1, imm=-1, resultado=1 📝 Executando instrução na posição PC=5 📥 Imediato lido: 0 (binário: 000000000000) 🏃 Executando JAL: salto para PC=3 📝 Executando instrução na posição PC=2 📥 Imediato lido: 4 (binário: 000000000100) 📝 Executando instrução na posição PC=3 📥 Imediato lido: 1 (binário: 000000000001) ➕ Executando ADD: rd=2, rs1=2, rs2=1, resultado=16 📝 Executando instrução na posição PC=4 📥 Imediato lido: -1 (binário: 111111111111) 🧮 Executando ADDI: rd=1, rs1=1, imm=-1, resultado=0 📝 Executando instrução na posição PC=5 📥 Imediato lido: 0 (binário: 000000000000) 🏃 Executando JAL: salto para PC=3 📝 Executando instrução na posição PC=2 📥 Imediato lido: 4 (binário: 000000000100) 🔀 BEQ: registradores iguais (rs1=1, rs2=0), desvio para PC=6

═════════════════════════════════════════════════════════════════ 🌟 Estado final dos registradores 🌟 r0: 0 r1: 0 r2: 16 r3: 0 r4: 0 r5: 0 r6: 0 r7: 0

📝 PC: 6 🧠 Memória (primeiros 10 valores): [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] ═════════════════════════════════════════════════════════════════ 👾 Simulação concluída 👾

DeboraSabrinaOPereira commented 1 month ago

Nova saída do compilador:

addi x1, x0, 5 #atribui 5 ao registrador x1
addi x2, x0, 1 #atribui 1 ao registrador x2
loop: #loop enquanto o registrador x1 for maior que x0
beq x1, x0, fim #sai do loop se x1 = x0
add x2, x2, x1 #soma x2 com x1
addi x1, x1, -1 #subtrai 1 de x1 para poder sair do loop quando chegar em 0
jal x0, loop #salta para o início do loop
fim: #programa encerra quando x1 = x0
nop

Fatorial(add).txt

DeboraSabrinaOPereira commented 1 month ago

@joaopedro1422 Nosso simulador teve resultado igual ao seu, mas a saída do compilador ainda está diferente:

Não sei ao certo o porquê das diferenças, mas vejo que no de vocês o "nop" tem o mesmo binário que o "jal". Acredito que o nop deveria ser 00000000000000000000000000010011, mas não tenho certeza. E aparentemente as linhas que estão diferentes são justamente de "beq" e "jal", o que implica dizer que estamos calculando os saltos de forma diferente. Nós alteramos o nosso cálculo de salto e agora só fazemos o seguinte, passamos a linha original onde está o rótulo como o offset.

Por exemplo, o rótulo loop está na linha 2, a instrução que for saltar para ele terá 2 no offset.

E seguimos esse padrão para formar o binário das instruções, obedecendo os intervalos do imm:

image

O nosso:

0b00000000010100000000000010010011
0b00000000000100000000000100010011
0b00000000000000001000011001100011
0b00000000000100010000000100110011
0b11111111111100001000000010010011
0b00000000010000000000000001101111
0b00000000000000000000000000010011

O de vocês:

00000000010100000000000010010011
00000000000100000000000100010011
00000000010000000000010001100011
00000000000100010000000100110011
11111111111100001000000010010011
00000000000000000011000001101111
00000000000000000011000001101111