import Head from 'next/head' import Image from 'next/image' import Table from 'react-bootstrap/Table' import Container from 'react-bootstrap/Container' import Nav from 'react-bootstrap/Nav' import Navbar from 'react-bootstrap/Navbar'; import NavDropdown from 'react-bootstrap/NavDropdown' import Row from 'react-bootstrap/Row' import Col from 'react-bootstrap/Col' import { useState } from 'react'; import Button from 'react-bootstrap/Button'; import { useContext } from 'react'; import { ProgramContext } from '../src/ProgramContext'; export default function Home() { const { program } = useContext(ProgramContext); //console.log(JSON.stringify(program)); let baseI = { issue: null, exeCompleta: null, write: null, busy: false, discart: false, } let instructions = []; for (let i = 0; i < program.length; i++) { instructions[i] = { posicao: i + 1, instrucao: program[i], ...baseI, }; } let baseFu = { instrucao: null, estadoInstrucao: null, tempo: null, ocupado: false, operacao: null, vj: null, vk: null, qj: null, qk: null, jump: false, }; let fUnites = [ { tipoUnidade: "Integer", nome: "Integer1", ...baseFu }, { tipoUnidade: "Integer", nome: "Integer2", ...baseFu }, { tipoUnidade: "Integer", nome: "Integer3", ...baseFu }, { tipoUnidade: "Add", nome: "Add1", ...baseFu }, { tipoUnidade: "Add", nome: "Add2", ...baseFu }, { tipoUnidade: "Add", nome: "Add3", ...baseFu }, { tipoUnidade: "Mult", nome: "Mult1", ...baseFu }, { tipoUnidade: "Mult", nome: "Mult2", ...baseFu } ]; let baseMu = { instrucao: null, estadoInstrucao: null, tempo: null, ocupado: false, qi: null, qj: null, operacao: null, endereco: null, destino: null, }; let mUnites = [ { tipoUnidade: "Load", nome: "Load1", ...baseMu }, { tipoUnidade: "Load", nome: "Load2", ...baseMu }, { tipoUnidade: "Load", nome: "Load3", ...baseMu }, { tipoUnidade: "Load", nome: "Load4", ...baseMu }, { tipoUnidade: "Load", nome: "Load5", ...baseMu }, { tipoUnidade: "Store", nome: "Store1", ...baseMu }, { tipoUnidade: "Store", nome: "Store2", ...baseMu }, { tipoUnidade: "Store", nome: "Store3", ...baseMu } ]; let registers = []; for (let i = 0; i < 10; i++) { registers[i] = null; } let [clock, setClock] = useState(1); let [instructionStatus, setInstructionStatus] = useState(instructions); let [functionalUnits, setFunctionalUnits] = useState(fUnites); let [memoryUnits, setMmoryUnits] = useState(mUnites); let [registerStatus, setRegisterStatus] = useState(registers); function fetchInstruction() { for (let i = 0; i < instructionStatus.length; i++) { let element = instructionStatus[i]; //console.log("element:", element.instrucao.operacao); if (element.issue === null && !element.discart) { return element; } } return undefined; } function getFunctionalUnity(instr) { //console.log("getFunctionalUnity:", instr.operacao); switch (instr.operacao) { case 'ADD': return 'Add' case 'BEQ': return 'Integer' case 'BNEZ': return 'Integer' case 'DIV': return 'Mult' case 'LD': return 'Load' case 'MULT': return 'Mult' case 'SD': return 'Store' case 'SUB': return 'Add' } } function getEmptyFunctionalUnity(tipoFU) { if ((tipoFU === 'Load') || (tipoFU === 'Store')) { for (let key in memoryUnits) { var ufMem = memoryUnits[key]; if (ufMem.tipoUnidade === tipoFU) { if (!ufMem.ocupado) { return ufMem; } } } return undefined; } for (let key in functionalUnits) { var uf = functionalUnits[key]; if (uf.tipoUnidade === tipoFU) { if (!uf.ocupado) { return uf; } } } return undefined; } function getCycles(instrucao) { switch (instrucao.operacao) { case 'ADD': return 1; case 'BEQ': return 1; case 'BNEZ': return 1; case 'DIV': return 1; case 'LD': return 1; case 'MULT': return 1; case 'SD': return 1; case 'SUB': return 1; } } function allocFunctionalUnit(uf, instrucao, estadoInstrucao) { uf.instrucao = instrucao; uf.estadoInstrucao = estadoInstrucao; uf.tempo = getCycles(instrucao) + 1; uf.ocupado = true; uf.operacao = instrucao.operacao; let reg_j; let reg_k; let reg_j_inst; let reg_k_inst; if ((instrucao.operacao === 'BNEZ') || (instrucao.operacao === 'BEQ')) { reg_j = registerStatus[instrucao.registradorR.replace('R', '')]; reg_k = registerStatus[instrucao.registradorS.replace('R', '')]; reg_j_inst = instrucao.registradorR; reg_k_inst = instrucao.registradorS; } else { reg_j = registerStatus[instrucao.registradorS.replace('R', '')]; reg_k = registerStatus[instrucao.registradorT.replace('R', '')]; reg_j_inst = instrucao.registradorS; reg_k_inst = instrucao.registradorT; } if (reg_j === null || reg_j === undefined) { uf.vj = reg_j_inst; } else { if ((reg_j in functionalUnits) || (reg_j in memoryUnits)) { uf.qj = reg_j; } else { uf.vj = reg_j; } } if (reg_k === null || reg_k === undefined) { uf.vk = reg_k_inst; } else { if ((reg_k in functionalUnits) || (reg_k in memoryUnits)) { uf.qk = reg_k; } else { uf.vk = reg_k; } } } function allocMemoryUnit(uf, instrucao, estadoInstrucao) { uf.instrucao = instrucao; uf.estadoInstrucao = estadoInstrucao; uf.tempo = getCycles(instrucao) + 1 uf.ocupado = true; uf.operacao = instrucao.operacao; uf.endereco = instrucao.registradorS + '+' + instrucao.registradorT; uf.destino = instrucao.registradorR; uf.qi = null; uf.qj = null; if (instrucao.operacao === 'SD') { let UFQueTemQueEsperar = registerStatus[instrucao.registradorR.replace('R', '')]; if ((UFQueTemQueEsperar in functionalUnits) || (UFQueTemQueEsperar in memoryUnits)) { uf.qi = UFQueTemQueEsperar; } else { uf.qi = null; } } let UFintQueTemQueEsperar = registerStatus[instrucao.registradorT.replace('R', '')]; if ((UFintQueTemQueEsperar in functionalUnits) || (UFintQueTemQueEsperar in memoryUnits)) { uf.qj = UFintQueTemQueEsperar; } else { uf.qj = null; } } function writeRegister(instrucao, entry) { registerStatus[instrucao.registradorR.replace('R', '')] = entry; setRegisterStatus(registerStatus); } function releaseWaitingUnity(UF) { for (let keyUF in functionalUnits) { const ufOlhando = functionalUnits[keyUF]; if ((ufOlhando.ocupado === true) && ((ufOlhando.qj === UF.nome) || (ufOlhando.qk === UF.nome))) { if (ufOlhando.qj === UF.nome) { ufOlhando.vj = 'VAL(' + UF.nome + ')'; ufOlhando.qj = null; } if (ufOlhando.qk === UF.nome) { ufOlhando.vk = 'VAL(' + UF.nome + ')'; ufOlhando.qk = null; } if ((ufOlhando.qj === null) && (ufOlhando.qk === null)) { ufOlhando.tempo = ufOlhando.tempo - 1; } } } for (let keyUF in memoryUnits) { const ufOlhando = memoryUnits[keyUF]; if (ufOlhando.ocupado === true) { if (ufOlhando.qi === UF.nome) { ufOlhando.qi = null; ufOlhando.tempo = ufOlhando.tempo - 1; } else if (ufOlhando.qj === UF.nome) { ufOlhando.qj = null; ufOlhando.tempo = ufOlhando.tempo - 1; } } } } function deallocFunctionalUnit(ufMem) { ufMem.instrucao = null; ufMem.estadoInstrucao = null; ufMem.tempo = null; ufMem.ocupado = false; ufMem.operacao = null; ufMem.endereco = null; ufMem.destino = null; ufMem.qi = null; ufMem.qj = null; } function deallocMemorylUnit(uf) { uf.instrucao = null; uf.estadoInstrucao = null; uf.tempo = null; uf.ocupado = false; uf.operacao = null; uf.vj = null; uf.vk = null; uf.qj = null; uf.qk = null; } function issueInstruction() { //console.log("issueInstruction"); let novaInstrucao = fetchInstruction(); if (novaInstrucao) { console.log(novaInstrucao); let ufInstrucao = getFunctionalUnity(novaInstrucao.instrucao); let UFParaUsar = getEmptyFunctionalUnity(ufInstrucao); if (UFParaUsar) { if ((UFParaUsar.tipoUnidade == 'Load') || (UFParaUsar.tipoUnidade == 'Store')) { allocMemoryUnit(UFParaUsar, novaInstrucao.instrucao, novaInstrucao); } else { allocFunctionalUnit(UFParaUsar, novaInstrucao.instrucao, novaInstrucao); } novaInstrucao.issue = clock; if ((UFParaUsar.tipoUnidade !== 'Store') && (UFParaUsar.operacao !== 'BEQ') && (UFParaUsar.operacao !== 'BNEZ')) { writeRegister(novaInstrucao.instrucao, novaInstrucao.posicao); } } } } function executeInstruction() { for (let key in memoryUnits) { var ufMem = memoryUnits[key]; if ((ufMem.ocupado) && (ufMem.qi === null) && (ufMem.qj === null)) { ufMem.tempo = ufMem.tempo - 1; if (ufMem.tempo === 0) { ufMem.estadoInstrucao.exeCompleta = clock; ufMem.estadoInstrucao.busy = false; } } } for (let key in functionalUnits) { var uf = functionalUnits[key]; if (uf.instrucao?.operacao === "BEQ") { if (uf.instrucao?.registradorR === uf.instrucao?.registradorS) { let entry = uf.estadoInstrucao.posicao; instructionStatus[entry].discart = true; instructionStatus[entry + 1].discart = true; setInstructionStatus(instructionStatus); } } if ((uf.ocupado) && (uf.vj !== null) && (uf.vk !== null)) { uf.tempo = uf.tempo - 1; uf.estadoInstrucao.busy = true; if (uf.tempo === 0) { uf.estadoInstrucao.exeCompleta = clock; uf.estadoInstrucao.busy = false; } } } } function writeInstruction() { for (let key in memoryUnits) { const ufMem = memoryUnits[key]; if (ufMem.ocupado) { if (ufMem.tempo === -1) { ufMem.estadoInstrucao.write = clock; let valorReg = registerStatus[ufMem.instrucao.registradorR.replace('R', '')]; if (valorReg === ufMem.nome) { registerStatus[ufMem.instrucao.registradorR.replace('R', '')] = 'VAL(' + ufMem.nome + ')'; } releaseWaitingUnity(ufMem); deallocMemorylUnit(ufMem); } } } for (let key in functionalUnits) { const uf = functionalUnits[key]; if (uf.ocupado && uf.tempo === -1) { uf.estadoInstrucao.write = clock; let valorReg = registerStatus[uf.instrucao.registradorR.replace('R', '')]; if (valorReg === uf.nome) { registerStatus[uf.instrucao.registradorR.replace('R', '')] = 'VAL(' + uf.nome + ')'; } releaseWaitingUnity(uf); deallocFunctionalUnit(uf); } } } function nextCycle() { setClock(clock + 1); console.log(clock); let jump = issueInstruction(); if (!jump) { executeInstruction(); writeInstruction(); } setInstructionStatus(instructionStatus); setMmoryUnits(memoryUnits); setFunctionalUnits(functionalUnits); } function getFormatedState(instr) { if (instr.discart) { return "Discarted"; } if (instr.write !== null) { return "Commit"; } if (instr.exeCompleta !== null) { return "Write Result"; } if (instr.issue !== null) { return "Execute"; } return "Issue"; } function reorderBufferValueFormat(instr) { switch (instr.instrucao.operacao) { case 'SUB': return {`${instr.instrucao.registradorS} - ${instr.instrucao.registradorT}`}; case 'MULT': return {`${instr.instrucao.registradorS} * ${instr.instrucao.registradorT}`}; case 'DIV': return {`${instr.instrucao.registradorS} / ${instr.instrucao.registradorT}`}; case 'LD': return {`Mem[${instr.instrucao.registradorS} + ${instr.instrucao.registradorT}]`}; case 'SD': return {`Mem[${instr.instrucao.registradorS} + ${instr.instrucao.registradorT}]`}; case 'ADD': return {`${instr.instrucao.registradorS} + ${instr.instrucao.registradorT}`}; case 'BEQ': return {`${instr.instrucao.registradorR} == ${instr.instrucao.registradorS}`}; case 'BNEZ': return {`${instr.instrucao.registradorR} != ${instr.instrucao.registradorS}`}; } } return ( <> Tomasulo Tomasulo

Ciclos: {clock}


Reorder Buffer

{instructionStatus.map((instr, index) => ( ))}
Entry Busy Instruction State Destination Value
{instr.posicao} {instr.busy ? "Yes" : "No"} {`${instr.instrucao.operacao} ${instr.instrucao.registradorR} ${instr.instrucao.registradorS} ${instr.instrucao.registradorT}`} {getFormatedState(instr)} {instr.instrucao.registradorR} {reorderBufferValueFormat(instr)}

Registers Status

{[0, 1, 2, 3, 4].map((i, j) => ( ))} {[5, 6, 7, 8, 9].map((i, j) => ( ))} {[10, 11, 12, 13, 14].map((i, j) => ( ))}
R0 R1 R2 R3 R4
{registerStatus[i]}
R5 R6 R7 R8 R9
{registerStatus[i]}
R10 R11 R12 R13 R14
{registerStatus[i]}

Reservation Stations (Load/Store)

{memoryUnits.map((unit, index) => ( ))}
Time Name Busy Address Destination
{unit.tempo} {unit.nome} {unit.ocupado ? "Yes" : "No"} {unit.endereco} {unit.destino}

Reservation Stations

{functionalUnits.map((unit, index) => ( ))}
Time Name Busy Op Vj Vk Qj Qk
{unit.tempo} {unit.nome} {unit.ocupado ? "Yes" : "No"} {unit.operacao} {unit.vj} {unit.vk} {unit.qj} {unit.qk}
Caio Arães, David Freitas, Guilherme Werner
) }