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,
}
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,
};
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) {
return element;
}
}
return undefined;
}
function getFunctionalUnity(instr) {
console.log("getFunctionalUnity:", instr.operacao);
switch (instr.operacao) {
case 'ADDD':
return 'Add'
case 'SUBD':
return 'Add'
case 'MULTD':
return 'Mult'
case 'DIVD':
return 'Mult'
case 'LD':
return 'Load'
case 'SD':
return 'Store'
case 'ADD':
return 'Integer'
case 'DADDUI':
return 'Integer'
case 'BEQ':
return 'Integer'
case 'BNEZ':
return 'Integer'
}
}
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 'ADDD':
return 1;
case 'SUBD':
return 1;
case 'MULTD':
return 1;
case 'DIVD':
return 1;
case 'LD':
return 1;
case 'SD':
return 1;
case 'ADD':
return 1;
case 'DADDUI':
return 1;
case 'BEQ':
return 1;
case 'BNEZ':
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','').replace('F','')];
reg_k = registerStatus[instrucao.registradorS.replace('R','').replace('F','')];
reg_j_inst = instrucao.registradorR;
reg_k_inst = instrucao.registradorS;
} else {
reg_j = registerStatus[instrucao.registradorS.replace('R','').replace('F','')];
reg_k = registerStatus[instrucao.registradorT.replace('R','').replace('F','')];
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','').replace('F','')];
if ((UFQueTemQueEsperar in functionalUnits) || (UFQueTemQueEsperar in memoryUnits)) {
uf.qi = UFQueTemQueEsperar;
}
else {
uf.qi = null;
}
}
let UFintQueTemQueEsperar = registerStatus[instrucao.registradorT.replace('R','').replace('F','')];
if ((UFintQueTemQueEsperar in functionalUnits) || (UFintQueTemQueEsperar in memoryUnits)) {
uf.qj = UFintQueTemQueEsperar;
}
else {
uf.qj = null;
}
}
function writeRegister(instrucao, ufNome) {
registerStatus[instrucao.registradorR.replace('R','').replace('F','')] = ufNome;
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) {
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 !== 'BEQ')) {
writeRegister(novaInstrucao.instrucao, UFParaUsar.nome);
}
}
}
}
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;
console.log("estado Instrucao", ufMem.estadoInstrucao);
if (ufMem.tempo === 0) {
ufMem.estadoInstrucao.exeCompleta = clock;
ufMem.estadoInstrucao.busy = false;
}
}
}
for (let key in functionalUnits) {
var uf = functionalUnits[key];
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','').replace('F','')];
if (valorReg === ufMem.nome) {
registerStatus[ufMem.instrucao.registradorR.replace('R','').replace('F','')] = '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','').replace('F','')];
if (valorReg === uf.nome) {
registerStatus[uf.instrucao.registradorR.replace('R','').replace('F','')] = 'VAL(' + uf.nome + ')';
}
releaseWaitingUnity(uf);
deallocFunctionalUnit(uf);
}
}
}
function nextCycle() {
setClock(clock + 1);
console.log(clock);
issueInstruction();
executeInstruction();
writeInstruction();
setInstructionStatus(instructionStatus);
setMmoryUnits(memoryUnits);
setFunctionalUnits(functionalUnits);
}
function getFormatedState(instr) {
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 'ADDD':
return {`${instr.instrucao.registradorS} + ${instr.instrucao.registradorT}`};
case 'SUBD':
return {`${instr.instrucao.registradorS} - ${instr.instrucao.registradorT}`};
case 'MULTD':
return {`${instr.instrucao.registradorS} * ${instr.instrucao.registradorT}`};
case 'DIVD':
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 'DADDUI':
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}
Instruction Status
Instruction |
Issued |
Execute |
Write Result |
{instructionStatus.map((instr, index) => (
{`${instr.instrucao.operacao} ${instr.instrucao.registradorR} ${instr.instrucao.registradorS} ${instr.instrucao.registradorT}`} |
{instr.issue} |
{instr.exeCompleta} |
{instr.write} |
))}
Reorder Buffer
Entry |
Busy |
Instruction |
State |
Destination |
Value |
{instructionStatus.map((instr, index) => (
{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)} |
))}
Reservation Stations (Load/Store)
Time |
Name |
Busy |
Address |
Destination |
{memoryUnits.map((unit, index) => (
{unit.tempo} |
{unit.nome} |
{unit.ocupado ? "Yes" : "No"} |
{unit.endereco} |
{unit.destino} |
))}
Reservation Stations
Time |
Name |
Busy |
Op |
Vj |
Vk |
Qj |
Qk |
{functionalUnits.map((unit, index) => (
{unit.tempo} |
{unit.nome} |
{unit.ocupado ? "Yes" : "No"} |
{unit.operacao} |
{unit.vj} |
{unit.vk} |
{unit.qj} |
{unit.qk} |
))}
Registers Status
F0 |
F1 |
F2 |
F3 |
F4 |
F5 |
F6 |
F7 |
F8 |
F9 |
{registerStatus.map((val, idx) => (
{val} |
))}
Caio Arães, David Freitas, Guilherme Werner
>
)
}