From 7bf244072606ef8798508cf2fc1f5dfc0a2dc70f Mon Sep 17 00:00:00 2001 From: Hunter Hedges <h.hedges@live.com> Date: Sat, 28 Apr 2018 19:32:53 -0500 Subject: [PATCH] Fix stalling and add more samples --- css/styles.min.css | 1 - index.html | 7 ++++-- js/mipsInstructions.js | 53 +++++++++++++++++++++++++++++++-------- js/mipsSimulator.min.js | 1 - js/simulate.js | 53 ++++++++++++++++++++++++++++++++++++--- sampleinputs/sample_1.txt | 2 +- sampleinputs/sample_3.txt | 12 +++++++++ sampleinputs/sample_4.txt | 16 ++++++++++++ sampleinputs/sample_5.txt | 29 +++++++++++++++++++++ 9 files changed, 155 insertions(+), 19 deletions(-) delete mode 100644 css/styles.min.css delete mode 100644 js/mipsSimulator.min.js create mode 100644 sampleinputs/sample_3.txt create mode 100644 sampleinputs/sample_4.txt create mode 100644 sampleinputs/sample_5.txt diff --git a/css/styles.min.css b/css/styles.min.css deleted file mode 100644 index ae24edb..0000000 --- a/css/styles.min.css +++ /dev/null @@ -1 +0,0 @@ -.navbar,.navbar a{color:#ecf0f1}body,html{height:100%}a:hover{text-decoration:none}#content-wrap{min-height:100%}#main{overflow:auto;padding:5px 5px 75px}.navbar{background:url(https://github.com/hunterhedges/mipsSimulator/blob/master/images/overlay.png?raw=true) #041942;font-family:'Open Sans',sans-serif}.navbar a:hover{color:#95a5a6}.navbar-toggler{border:1px solid #fff}.navbar-toggler-icon{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 32 32' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba(255, 255, 255, 1)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 8h24M4 16h24M4 24h24'/%3E%3C/svg%3E")}footer{position:relative;clear:both;background:url(https://github.com/hunterhedges/mipsSimulator/blob/master/images/overlay.png?raw=true) #041942;height:75px;margin-top:-75px}.decoded-instructions-container,.simulation-results-container{border:3px dotted #000;padding:10px;margin-top:20px;margin-bottom:20px}.upload-container{min-height:500px;display:flex;border:3px dotted #000;font-size:22px}.file-input{display:none}.upload-icon{max-width:100%;width:50%}.file-hover{background-color:#e6e6e6}.demo-link{position:absolute;top:10px;right:20px;font-size:16px}.decoded-instructions-container{display:none;font-size:22px}.decoded-instructions-container h4{margin-bottom:20px}.decoded-instructions-container p{text-align:left;font-size:16px}.simulation-results-container{display:none}@media(max-width:320px){.navbar-brand{font-size:18px}}@media (min-width:992px){.upload-icon{width:35%}.upload-container{margin-top:20px;margin-bottom:20px}} diff --git a/index.html b/index.html index cfeb02f..578e64a 100644 --- a/index.html +++ b/index.html @@ -9,7 +9,7 @@ <!-- Bootstrap CSS --> <link href="depends/bootstrap-4.0.0/css/bootstrap.min.css" rel="stylesheet" /> <!-- Site CSS --> - <link href="css/styles.min.css" rel="stylesheet" /> + <link href="css/styles.css" rel="stylesheet" /> <!-- jQuery --> <script src="depends/jquery-3.3.1.min.js"></script> <!-- Bootstrap JS --> @@ -202,7 +202,10 @@ <h5 class="modal-title" id="modalTitle"><!-- Modal Title --></h5> </div> <!-- End Error Modal --> - <script src="js/mipsSimulator.min.js"></script> + <script src="js/extensions.js"></script> + <script src="js/parseInputFile.js"></script> + <script src="js/mipsInstructions.js"></script> + <script src="js/simulate.js"></script> </body> </html> diff --git a/js/mipsInstructions.js b/js/mipsInstructions.js index 61efeca..b13c391 100644 --- a/js/mipsInstructions.js +++ b/js/mipsInstructions.js @@ -1,6 +1,7 @@ const ACTIONS = { DECODE: "decode", - EXECUTE: "execute" + EXECUTE: "execute", + SHOULD_STALL: "stall" } // ExecutionResult object returned by MIPS instruction on execute action. @@ -10,8 +11,9 @@ const ACTIONS = { // Memory location and value object affected if applicable // Bool if the instruction causes a branch // Integer of branch offset if shouldBranch = true -function ExecutionResult(stallAmount, registerState, memoryState, shouldBranch, branchOffset) { +function ExecutionResult(stallLocation, stallAmount, registerState, memoryState, shouldBranch, branchOffset) { + this.stallLocation = stallLocation; this.stallAmount = stallAmount; this.registerState = registerState; this.memoryState = memoryState; @@ -196,13 +198,17 @@ function add(binaryInstructionString, action) { setRegisterDefault(rs); setRegisterDefault(rt); + var stallLocation = rd; var stallAmount = 2; var registerState = { register: rd, value: registers[rs] + registers[rt] }; var memoryState = null; var shouldBranch = false; var branchOffset = 0; - return new ExecutionResult(stallAmount, registerState, memoryState, shouldBranch, branchOffset); + return new ExecutionResult(stallLocation, stallAmount, registerState, memoryState, shouldBranch, branchOffset); + } + else if(action == ACTIONS.SHOULD_STALL) { + return [rs, rt]; } } @@ -222,13 +228,17 @@ function addi(binaryInstructionString, action) { else if(action == ACTIONS.EXECUTE) { setRegisterDefault(rs); + var stallLocation = rt; var stallAmount = 2; var registerState = { register: rt, value: registers[rs] + imm }; var memoryState = null; var shouldBranch = false; var branchOffset = 0; - return new ExecutionResult(stallAmount, registerState, memoryState, shouldBranch, branchOffset); + return new ExecutionResult(stallLocation, stallAmount, registerState, memoryState, shouldBranch, branchOffset); + } + else if(action == ACTIONS.SHOULD_STALL) { + return [rs]; } } @@ -260,7 +270,10 @@ function branchOnEqual(binaryInstructionString, action) { branchOffset = offset; } - return new ExecutionResult(stallAmount, registerState, memoryState, shouldBranch, branchOffset); + return new ExecutionResult(null, stallAmount, registerState, memoryState, shouldBranch, branchOffset); + } + else if(action == ACTIONS.SHOULD_STALL) { + return [rs, rt]; } } @@ -292,7 +305,10 @@ function branchNotEqual(binaryInstructionString, action) { branchOffset = offset; } - return new ExecutionResult(stallAmount, registerState, memoryState, shouldBranch, branchOffset); + return new ExecutionResult(null, stallAmount, registerState, memoryState, shouldBranch, branchOffset); + } + else if(action == ACTIONS.SHOULD_STALL) { + return [rs, rt]; } } @@ -314,14 +330,17 @@ function loadWord(binaryInstructionString, action) { setRegisterDefault(rs); setMemoryDefault(rs + offset); + var stallLocation = rt; var stallAmount = 2; var registerState = { register: rt, value: memory[registers[rs] + offset] }; var memoryState = null; var shouldBranch = false; var branchOffset = 0; - return new ExecutionResult(stallAmount, registerState, memoryState, shouldBranch, branchOffset); - + return new ExecutionResult(stallLocation, stallAmount, registerState, memoryState, shouldBranch, branchOffset); + } + else if(action == ACTIONS.SHOULD_STALL) { + return [rs]; } } @@ -349,7 +368,10 @@ function storeWord(binaryInstructionString, action) { var shouldBranch = false; var branchOffset = 0; - return new ExecutionResult(stallAmount, registerState, memoryState, shouldBranch, branchOffset); + return new ExecutionResult(null, stallAmount, registerState, memoryState, shouldBranch, branchOffset); + } + else if(action == ACTIONS.SHOULD_STALL) { + return [rs, rt]; } } @@ -380,11 +402,16 @@ function setOnLessThan(binaryInstructionString, action) { registerState = { register: rd, value: 0 }; } + var stallLocation = rd; + var stallAmount = 2; var memoryState = null; var shouldBranch = false; var branchOffset = 0; - return new ExecutionResult(stallAmount, registerState, memoryState, shouldBranch, branchOffset); + return new ExecutionResult(stallLocation, stallAmount, registerState, memoryState, shouldBranch, branchOffset); + } + else if(action == ACTIONS.SHOULD_STALL) { + return [rs, rt]; } } @@ -405,13 +432,17 @@ function sub(binaryInstructionString, action) { setRegisterDefault(rs); setRegisterDefault(rt); + var stallLocation = rd; var stallAmount = 2; var registerState = { register: rd, value: registers[rs] - registers[rt] }; var memoryState = null; var shouldBranch = false; var branchOffset = 0; - return new ExecutionResult(stallAmount, registerState, memoryState, shouldBranch, branchOffset); + return new ExecutionResult(stallLocation, stallAmount, registerState, memoryState, shouldBranch, branchOffset); + } + else if(action == ACTIONS.SHOULD_STALL) { + return [rs, rt]; } } diff --git a/js/mipsSimulator.min.js b/js/mipsSimulator.min.js deleted file mode 100644 index 9a3c18e..0000000 --- a/js/mipsSimulator.min.js +++ /dev/null @@ -1 +0,0 @@ -var SECTIONS={REGISTERS:{sectionName:"registers",stopCharacters:["m","c"]},MEMORY:{sectionName:"memory",stopCharacters:["r","c"]},CODE:{sectionName:"code",stopCharacters:["r","m"]}},registers={},memory={},decodedCode=[],warnings=[];function canDoDragAndDrop(){var e=document.createElement("div");return("draggable"in e||"ondragstart"in e&&"ondrop"in e)&&"FormData"in window&&"FileReader"in window}function readDemoFile(){$.get("https://raw.githubusercontent.com/hunterhedges/mipsSimulator/master/sampleinputs/sample_1.txt",function(e){parseInputFile(e)})}function readFileOnUpload(e){var t;if("drop"==e.type?t=e.originalEvent.dataTransfer.files[0]:"change"==e.type&&(t=$("#file")[0].files[0]),t.type.includes("text")){var r=new FileReader;r.onload=function(e){var t=e.target.result;t.isNullOrEmpty()?showModal("Error Uploading File","File is empty"):parseInputFile(t)},r.readAsText(t)}else showModal("Error Uploading File","Incorrect file type")}function parseInputFile(e){reset(),loadRegisters(parseSection(e=e.toLowerCase(),SECTIONS.REGISTERS)),loadMemory(parseSection(e,SECTIONS.MEMORY)),loadDecodedCode(parseSection(e,SECTIONS.CODE)),displayDecodedInstructions(),displayWarnings()}function parseSection(e,t){var r,n="",s=0;if(e.includes(t.sectionName)){for(s=e.indexOf(t.sectionName)+t.sectionName.length;!t.stopCharacters.includes(e.charAt(s))&&s<e.length;)n+=e.charAt(s),s++;r=(r=n.split("\n")).removeEmptyElements()}else warnings.push("<strong>"+t.sectionName.toUpperCase()+"</strong> section not found in file.");return r}function loadRegisters(e){if(e)for(var t=0;t<e.length;t++){for(var r=0,n="",s="";" "!=e[t].charAt(r)&&r<e[t].length;)n+=e[t].charAt(r),r++;for(r+=1;r<e[t].length;r++)s+=e[t].charAt(r);"r"==n.charAt(0)&&(n=n.replace("r","")),isValidRegister(n)&&isValidValue(s)&&(s=parseInt(s),registers[n]=s)}}function isValidRegister(e){var t,r=!1;return(t=parseInt(e))||0==t?t>0&&t<32?r=!0:warnings.push("Register <strong>"+e+"</strong> must be between 1 and 31 inclusive."):warnings.push("Register <strong>"+e+"</strong> could not be parsed."),r}function loadMemory(e){if(e)for(var t=0;t<e.length;t++){for(var r=0,n="",s="";" "!=e[t].charAt(r)&&r<e[t].length;)n+=e[t].charAt(r),r++;for(r+=1;r<e[t].length;r++)s+=e[t].charAt(r);"m"==n.charAt(0)&&(n=n.replace("m","")),isValidMemoryLocation(n)&&isValidValue(s)&&(s=parseInt(s),memory[n]=s)}}function isValidMemoryLocation(e){var t,r=!1;return(t=parseInt(e))?t>=0&&t<65280&&t%4==0?r=!0:warnings.push("Memory location <strong>"+e+"</strong> must be greater than 0, less than 65280, and divisible by 4."):warnings.push("Memory location <strong>"+e+"</strong> could not be parsed."),r}function loadDecodedCode(e){if(e)for(var t=0;t<e.length;t++){e[t]=e[t].replace(/ /g,"");var r=findInstruction(e[t],ACTIONS.DECODE);r?(decodedCode.push(r),instructions.push(e[t])):warnings.push("Code <strong>"+e[t]+"</strong> is not a valid instruction.")}}function isValidValue(e){var t=!1;return(e=parseInt(e,10))||0==e?e<=4294967295&&e>=-2147483648?t=!0:warnings.push("Value <strong>"+e+"</strong> will result in overflow."):warnings.push("Value <strong>"+e+"</strong> could not be parsed."),t}function displayDecodedInstructions(){for(var e in $("#decodedInstructionsContainer").show(),$("#decodedInstructions").append("REGISTERS<br />"),registers)$("#decodedInstructions").append("R"+e+" "+registers[e]+"<br />");for(var e in 0==registers.length&&$("#decodedInstructions").append("All registers set to 0<br />"),$("#decodedInstructions").append("<br />"),$("#decodedInstructions").append("MEMORY<br />"),memory)$("#decodedInstructions").append(e+" "+memory[e]+"<br />");0==memory.length&&$("#decodedInstructions").append("All memory locations set to 0<br />"),$("#decodedInstructions").append("<br />"),$("#decodedInstructions").append("CODE<br />");for(var t=0;t<decodedCode.length;t++)$("#decodedInstructions").append(decodedCode[t]+"<br />");0==decodedCode.length&&$("#decodedInstructions").append("No code detected"),$("html, body").animate({scrollTop:$("#decodedInstructionsContainer").offset().top-20},500)}function displayWarnings(){if(0!=warnings.length){for(var e="",t=0;t<warnings.length;t++)e+=t+1+". "+warnings[t]+"<br />";showModal("Warnings",e)}}function showModal(e,t){$("#modalTitle").html(e),$("#modalBody").html(t),$("#modal").modal("show")}function reset(){$("#decodedInstructionsContainer").hide(),$("#decodedInstructions").html(""),$("#simulationResultsContainer").hide(),$("#simulationInstructions").html(""),$("#simulationRegisters").html(""),$("#simulationMemory").html(""),$("#simulationCycleData").html(""),registers={},memory={},decodedCode=[],warnings=[],instructions=[],registerStates=[],memoryStates=[],cycleData=[],pcCounter=0,cycleCounter=1,$("html, body").animate({scrollTop:0},500)}$(function(){canDoDragAndDrop||$("#dragDropAvailable").hide(),$("#uploadContainer").on("drag dragstart dragend dragover dragenter dragleave drop",function(e){e.preventDefault(),e.stopPropagation()}),$("#uploadContainer").on("dragenter dragover",function(){$("#uploadContainer").addClass("file-hover")}),$("#uploadContainer").on("dragleave dragend drop",function(){$("#uploadContainer").removeClass("file-hover")}),$("#uploadContainer").on("drop",readFileOnUpload),$("input[type='file']").change(readFileOnUpload),$("#uploadLink").on("click",function(e){e.preventDefault(),$("#file:hidden").trigger("click")})});var ACTIONS={DECODE:"decode",EXECUTE:"execute"};function ExecutionResult(e,t,r,n,s){this.stallAmount=e,this.registerState=t,this.memoryState=r,this.shouldBranch=n,this.branchOffset=s}function findInstruction(e,t){var r;switch((e=e.trim()).substring(0,6)){case"000000":var n=e.substring(26);"100000"==n?r=add(e,t):"100010"==n?r=sub(e,t):"101010"==n&&(r=setOnLessThan(e,t));break;case"001000":r=addi(e,t);break;case"000100":r=branchOnEqual(e,t);break;case"000101":r=branchNotEqual(e,t);break;case"100011":r=loadWord(e,t);break;case"101011":r=storeWord(e,t)}return r}function parseRs(e){var t=e.substring(6,11);return parseInt(t,2)}function parseRt(e){var t=e.substring(11,16);return parseInt(t,2)}function parseRd(e){var t=e.substring(16,21);return parseInt(t,2)}function parseOffset(e){var t=e.substring(16);return parseInt(t,2)}function parseImm(e){var t=e.substring(16);return t=uintToInt(t=parseInt(t,2),10)}function setRegisterDefault(e){registers[e]||(registers[e]=0)}function setMemoryDefault(e){memory[e]||(memory[e]=0)}function add(e,t){var r=parseRs(e),n=parseRt(e),s=parseRd(e);if(t==ACTIONS.DECODE)return"ADD R"+s+", R"+r+", R"+n;if(t==ACTIONS.EXECUTE){setRegisterDefault(r),setRegisterDefault(n);return new ExecutionResult(2,{register:s,value:registers[r]+registers[n]},null,!1,0)}}function addi(e,t){var r=parseRs(e),n=parseRt(e),s=parseImm(e);if(t==ACTIONS.DECODE)return"ADDI R"+n+", R"+r+", "+s;if(t==ACTIONS.EXECUTE){setRegisterDefault(r);return new ExecutionResult(2,{register:n,value:registers[r]+s},null,!1,0)}}function branchOnEqual(e,t){var r=parseRs(e),n=parseRt(e),s=parseOffset(e);if(t==ACTIONS.DECODE)return"BEQ R"+r+", R"+n+", "+s;if(t==ACTIONS.EXECUTE){setRegisterDefault(r),setRegisterDefault(n);var a=!1,o=0;return registers[r]==registers[n]&&(a=!0,o=s),new ExecutionResult(0,null,null,a,o)}}function branchNotEqual(e,t){var r=parseRs(e),n=parseRt(e),s=parseOffset(e);if(t==ACTIONS.DECODE)return"BNE R"+r+", R"+n+", "+s;if(t==ACTIONS.EXECUTE){setRegisterDefault(r),setRegisterDefault(n);var a=!1,o=0;return registers[r]!=registers[n]&&(a=!0,o=s),new ExecutionResult(0,null,null,a,o)}}function loadWord(e,t){var r=parseRs(e),n=parseRt(e),s=parseOffset(e);if(t==ACTIONS.DECODE)return"LW R"+n+", "+s+"(R"+r+")";if(t==ACTIONS.EXECUTE){setRegisterDefault(n),setRegisterDefault(r),setMemoryDefault(r+s);return new ExecutionResult(2,{register:n,value:memory[registers[r]+s]},null,!1,0)}}function storeWord(e,t){var r=parseRs(e),n=parseRt(e),s=parseOffset(e);if(t==ACTIONS.DECODE)return"SW R"+n+", "+s+"(R"+r+")";if(t==ACTIONS.EXECUTE){setRegisterDefault(n),setRegisterDefault(r),setMemoryDefault(r+s);return new ExecutionResult(0,null,{memoryLocation:registers[r]+s,value:registers[n]},!1,0)}}function setOnLessThan(e,t){var r=parseRs(e),n=parseRt(e),s=parseRd(e);if(t==ACTIONS.DECODE)return"SLT R"+s+", R"+r+", R"+n;if(t==ACTIONS.EXECUTE){setRegisterDefault(r),setRegisterDefault(n);return new ExecutionResult(2,registers[r]<registers[n]?{register:s,value:1}:{register:s,value:0},null,!1,0)}}function sub(e,t){var r=parseRs(e),n=parseRt(e),s=parseRd(e);if(t==ACTIONS.DECODE)return"SUB R"+s+", R"+r+", R"+n;if(t==ACTIONS.EXECUTE){setRegisterDefault(r),setRegisterDefault(n);return new ExecutionResult(2,{register:s,value:registers[r]-registers[n]},null,!1,0)}}var previousExecutionResult,instructions=[],registerStates=[],memoryStates=[],cycleData=[],currentStep=0,pcCounter=0,cycleCounter=1;function stepThrough(){"END"!=decodedCode[decodedCode.length-1]&&decodedCode.push("END"),simulationReset(),simulate(),$("#simulationResultsContainer").show(),displayInstructions(0),displayRegisters(0),displayMemory(0),displayCycleData(0),setDownloadLink(),$("#prevStepBtn").attr("disabled","disabled"),$("#nextStepBtn").removeAttr("disabled"),$("html, body").animate({scrollTop:$("#simulationResultsContainer").offset().top-20},500)}function nextStep(){displayInstructions(++currentStep),displayRegisters(currentStep),displayMemory(currentStep),displayCycleData(currentStep),currentStep==decodedCode.length-1&&$("#nextStepBtn").attr("disabled","disabled"),0!=currentStep&&$("#prevStepBtn").removeAttr("disabled")}function previousStep(){displayInstructions(--currentStep),displayRegisters(currentStep),displayMemory(currentStep),displayCycleData(currentStep),0==currentStep&&$("#prevStepBtn").attr("disabled","disabled"),currentStep!=decodedCode.length-1&&$("#nextStepBtn").removeAttr("disabled")}function executeAll(){"END"!=decodedCode[decodedCode.length-1]&&decodedCode.push("END"),simulationReset(),currentStep=decodedCode.length-1,simulate(),$("#simulationResultsContainer").show(),displayInstructions(decodedCode.length-1),displayRegisters(registerStates.length-1),displayMemory(memoryStates.length-1),displayCycleData(cycleData.length),setDownloadLink(),$("#nextStepBtn").attr("disabled","disabled"),$("#prevStepBtn").removeAttr("disabled"),$("html, body").animate({scrollTop:$("#simulationResultsContainer").offset().top-20},500)}function displayInstructions(e){$("#simulationInstructions").html("");for(var t=0;t<decodedCode.length;t++)t==e?$("#simulationInstructions").append("<tr><td>→</td><td>"+decodedCode[t]+"</td></tr>"):$("#simulationInstructions").append("<tr><td></td><td>"+decodedCode[t]+"</td></tr>")}function displayRegisters(e){for(var t in $("#simulationRegisters").html(""),registerStates[e])registerStates[e][t]&&$("#simulationRegisters").append("<tr><td>R"+t+"</td><td>"+registerStates[e][t]+"</td></tr>")}function displayMemory(e){for(var t in $("#simulationMemory").html(""),memoryStates[e])memoryStates[e][t]&&$("#simulationMemory").append("<tr><td>"+t+"</td><td>"+memoryStates[e][t]+"</td></tr>")}function displayCycleData(e){$("#simulationCycleNumber").html(""),$("#simulationCycleData").html(""),$("#clockCycleTitle").attr("colspan",cycleCounter);for(var t=1;t<cycleCounter;t++)$("#simulationCycleNumber").append("<td>"+t+"</td>");for(t=0;t<e;t++){$("#simulationCycleData").append("<tr>");for(var r=1;r<cycleCounter;r++)r<cycleData[t].length&&cycleData[t][r]?$("#simulationCycleData").append("<td>"+cycleData[t][r]+"</td>"):$("#simulationCycleData").append("<td></td>");$("#simulationCycleData").append("</tr>")}}function simulate(){for(registerStates.push(Object.assign({},registers)),memoryStates.push(Object.assign({},memory));pcCounter<instructions.length;){var e=decodeAndExecute(instructionFetch());e?(previousExecutionResult=e,writeMemory(e),writeBack(e),pcCounter++,cycleCounter-=4):previousExecutionResult=null}cycleCounter+=4}function instructionFetch(){return cycleData.push([]),cycleData[pcCounter][cycleCounter]="I"+(pcCounter+1)+"-IF",cycleCounter++,instructions[pcCounter]}function decodeAndExecute(e){if(previousExecutionResult&&(stall(previousExecutionResult.stallAmount),previousExecutionResult.shouldBranch))return pcCounter+=previousExecutionResult.branchOffset,cycleCounter++,memoryStates.push(Object.assign({},memoryStates[memoryStates.length-1])),void registerStates.push(Object.assign({},registerStates[registerStates.length-1]));cycleData[pcCounter][cycleCounter]="I"+(pcCounter+1)+"-ID",cycleCounter++;var t=findInstruction(e,ACTIONS.EXECUTE);return cycleData[pcCounter][cycleCounter]="I"+(pcCounter+1)+"-EX",cycleCounter++,t}function writeMemory(e){if(e.memoryState){var t=Object.assign({},memory),r=e.memoryState.memoryLocation,n=e.memoryState.value;t[r]=n,memoryStates.push(t),memory[r]=n}else memoryStates.push(Object.assign({},memoryStates[memoryStates.length-1]));cycleData[pcCounter][cycleCounter]="I"+(pcCounter+1)+"-MEM",cycleCounter++}function writeBack(e){if(e.registerState){var t=Object.assign({},registers),r=e.registerState.register,n=e.registerState.value;t[r]=n,registerStates.push(t),registers[r]=n}else registerStates.push(Object.assign({},registerStates[registerStates.length-1]));cycleData[pcCounter][cycleCounter]="I"+(pcCounter+1)+"-WB",cycleCounter++}function stall(e){for(var t=0;t<e;t++)cycleData[pcCounter][cycleCounter]="I"+(pcCounter+1)+"-stall",cycleCounter++}function simulationReset(){0!=registerStates.length&&(registers=registerStates[0]),0!=memoryStates.length&&(memory=memoryStates[0]),registerStates=[],memoryStates=[],cycleData=[],currentStep=0,pcCounter=0,cycleCounter=1,previousExecutionResult=null}function setDownloadLink(){for(var e="",t=1;t<cycleCounter;t++){e+="c#"+t;for(var r=0;r<cycleData.length;r++)cycleData[r][t]&&(e+=" "+cycleData[r][t]);e+="\n"}for(var n in e+="REGISTERS\n",registerStates[registerStates.length-1])0!=registerStates[registerStates.length-1][n]&&(e+="R"+n+" "+registerStates[registerStates.length-1][n]+"\n");for(var n in e+="MEMORY\n",memoryStates[memoryStates.length-1])0!=memoryStates[memoryStates.length-1][n]&&(e+=n+" "+memoryStates[memoryStates.length-1][n]+"\n");var s="data:application/octet-stream;charset=utf-8;base64,"+btoa(e);$("#downloadLink").attr("href",s)}function uintToInt(e,t){return e<<=32-(t=+t||32),e>>=32-t}Array.prototype.removeEmptyElements=function(){for(var e=[],t=0;t<this.length;t++)this[t].isNullOrEmpty()||e.push(this[t]);return e},String.prototype.isNullOrEmpty=function(){return!this||/^\s*$/.test(this)}; diff --git a/js/simulate.js b/js/simulate.js index bb058e0..4509407 100644 --- a/js/simulate.js +++ b/js/simulate.js @@ -9,6 +9,8 @@ var pcCounter = 0; var cycleCounter = 1; var previousExecutionResult; +var secondPreviousResult; +var didPreviousStall = false; // Initiate the step through. Get simulation data, then show // it starting with the initial conditions. Disable previous @@ -249,6 +251,9 @@ function simulate() { var executionResult = decodeAndExecute(instruction); if(executionResult) { + + secondPreviousResult = previousExecutionResult; + previousExecutionResult = executionResult; writeMemory(executionResult); @@ -257,7 +262,7 @@ function simulate() { pcCounter++; - cycleCounter = cycleCounter - 4; + cycleCounter -= 4; } else { previousExecutionResult = null; @@ -278,7 +283,10 @@ function simulate() { // String of 32-bit binary instruction corresponding to pcCounter function instructionFetch() { - cycleData.push([]); + while(!cycleData[pcCounter]) { + cycleData.push([]); + } + cycleData[pcCounter][cycleCounter] = "I" + (pcCounter + 1) + "-IF"; cycleCounter++; @@ -297,8 +305,27 @@ function instructionFetch() { // case of previousExecutionResult being a branch function decodeAndExecute(instructionBinary) { + var shouldStall = false; + var stallLocations = findInstruction(instructionBinary, ACTIONS.SHOULD_STALL); + if(previousExecutionResult) { - stall(previousExecutionResult.stallAmount); + + if(previousExecutionResult.stallLocation) { + + for(var i = 0; i < stallLocations.length; i++) { + if(stallLocations[i] == previousExecutionResult.stallLocation) { + shouldStall = true; + } + } + + if(shouldStall) { + stall(previousExecutionResult.stallAmount); + didPreviousStall = true; + } + else { + didPreviousStall = false; + } + } if(previousExecutionResult.shouldBranch) { pcCounter += previousExecutionResult.branchOffset; @@ -309,6 +336,26 @@ function decodeAndExecute(instructionBinary) { return; } + + } + + if(secondPreviousResult && !didPreviousStall) { + + if(secondPreviousResult.stallLocation) { + + var shouldStallSecond = false; + + for(var i = 0; i < stallLocations.length; i++) { + if(stallLocations[i] == secondPreviousResult.stallLocation) { + shouldStallSecond = true; + } + } + + if(shouldStallSecond) { + stall(secondPreviousResult.stallAmount - 1); + } + + } } cycleData[pcCounter][cycleCounter] = "I" + (pcCounter + 1) + "-ID"; diff --git a/sampleinputs/sample_1.txt b/sampleinputs/sample_1.txt index fb965e2..3c2ca3a 100644 --- a/sampleinputs/sample_1.txt +++ b/sampleinputs/sample_1.txt @@ -9,6 +9,6 @@ CODE 10001100001000100000000000000000 00000000010000110010000000100000 10101100001001000000000000000000 -00010100000001000000000000000001 +00010100000001000000000000000010 00100000010000011111111111110111 00000000001000110000100000100000 diff --git a/sampleinputs/sample_3.txt b/sampleinputs/sample_3.txt new file mode 100644 index 0000000..1c4636d --- /dev/null +++ b/sampleinputs/sample_3.txt @@ -0,0 +1,12 @@ +// This sample demonstrates a data hazard stall + +// add r3, r1, r2 +// add r4, r3, r2 + +REGISTERS +R1 10 +R2 20 + +CODE +0000 0000 0010 0010 0001 1000 0010 0000 +0000 0000 0110 0010 0010 0000 0010 0000 \ No newline at end of file diff --git a/sampleinputs/sample_4.txt b/sampleinputs/sample_4.txt new file mode 100644 index 0000000..1352ea6 --- /dev/null +++ b/sampleinputs/sample_4.txt @@ -0,0 +1,16 @@ +// This sample should not stall + +// add rd, rs, rt +// rd = rs + rt +// 0000 00ss ssst tttt dddd d000 0010 0000 + +// add r3, r1, r2 +// add r4, r1, r2 + +REGISTERS +R1 10 +R2 20 + +CODE +0000 0000 0010 0010 0001 1000 0010 0000 +0000 0000 0010 0010 0010 0000 0010 0000 \ No newline at end of file diff --git a/sampleinputs/sample_5.txt b/sampleinputs/sample_5.txt new file mode 100644 index 0000000..48fe36d --- /dev/null +++ b/sampleinputs/sample_5.txt @@ -0,0 +1,29 @@ +// lw rt, offset(rs) +// rt = MEM[rs + offset] +// 1000 11ss ssst tttt iiii iiii iiii iiii + +// addi rs, rt, imm +// rt = rs + imm +// 0010 00ss ssst tttt iiii iiii iiii iiii + +// bne rs, rt, offset +// if(rs != rt) advance pc offset << 2 +// 0001 01ss ssst tttt iiii iiii iiii iiii + +//LW R2, 0(R1) +//ADDI R5, R2, 1 +//BNE R5, R1, 2 + +REGISTERS +R1 4 + +MEMORY +M4 12 + +CODE +1000 1100 0010 0010 0000 0000 0000 0000 +0010 0000 0100 0101 0000 0000 0000 0001 +0001 0100 1010 0001 0000 0000 0000 0010 +0010 0000 0100 0101 0000 0000 0000 0001 +0010 0000 0100 0101 0000 0000 0000 0001 +0010 0000 0100 0101 0000 0000 0000 0001 \ No newline at end of file