forked from asteriskman7/dldtg
-
Notifications
You must be signed in to change notification settings - Fork 0
/
cycle_sim-min_ORIG.js
1 lines (1 loc) · 14.2 KB
/
cycle_sim-min_ORIG.js
1
"use strict";var cycle_sim={hw:{},graphsEnabled:true,logElement:undefined,testFinished:undefined,eSimTime:undefined,simTickIterations:1,intervalID:undefined,simCyclesPerSecond:20,currentCyclesPerSecond:20,speedIndex:4,speedNames:["1/16x","1/8x","1/4x","1/2x","1x","2x","4x","8x","16x","max"],speedList:[1.25,2.5,5,10,20,40,80,160,320,1000],speedMax:false,nandCount:0,log:function(a){cycle_sim.logElement.value+=a+"\n";cycle_sim.logElement.scrollTop=cycle_sim.logElement.scrollHeight},simLog:function(a){cycle_sim.log("@T="+cycle_sim.hw.time+" "+a)},netlistErrorLog:function(b,c,a){cycle_sim.log("ERROR: (line "+c+") "+b+"\n"+a)},testFail:function(a,b){cycle_sim.simLog("TEST_FAIL\nREASON: "+b);cycle_sim.hw.testStatus="FAIL";cycle_sim.simPause();cycle_sim.testFinished(-1);ga("send","event","cycle_sim","test_fail",a)},testPass:function(a,b){cycle_sim.simLog("TEST PASS\nREASON: All tests were successful");cycle_sim.hw.testStatus="PASS";cycle_sim.simPause();cycle_sim.testFinished(b);ga("send","event","cycle_sim","test_pass",a)},randomBool:function(){return Math.random()>0.5},randomInt:function(b,a){return Math.floor(Math.random()*(a-b+1))+b},intToBoolList:function(d,b){var a=[];var c;for(c=0;c<b;c++){a[c]=Boolean(d&1);d=d>>1}return a},boolListToInt:function(c){var a=0;var b;for(b=c.length-1;b>=0;b--){a=(a<<1)|(c[b]?1:0)}return a},leftPadNumberString:function(b,a){while(b.length<a){b="0"+b}return b},findObjByProp:function(b,e,d){var c;for(c=0;c<b.length;c++){if(b[c][e]===d){return b[c]}}return undefined},getSigVal:function(b,a){return cycle_sim.hw.signals[b.nets[a].signal].value},getSigVecVal:function(f,d,b,e){var a=0;var c;for(c=b;c>=e;c--){a=(a<<1)+cycle_sim.hw.signals[f.nets[d+"<"+c+">"].signal].value}return a},setSigVal:function(b,a,d){var c=b.nets[a].signal;if(c>1){cycle_sim.hw.signals[c].next=d}},setSigVecVal:function(g,d,a,f,h){var c;var b;var e;for(c=f;c<=a;c++){b=h&1;h=h>>1;e=g.nets[d+"<"+c+">"].signal;cycle_sim.hw.signals[e].next=(b===1)}},expandNet:function(f){if(f.length===0){return[]}var d=f.split(",");var c;var g=/(<([0-9]+):?([0-9]*)>)$/;var b;var k=[];var a;var e;var h;var j;for(c=0;c<d.length;c++){b=g.exec(d[c]);if(b){a=b[2];e=b[3];if(b[3].length===0){k.push(d[c])}else{j=d[c].split("<")[0];if(a===e){k.push(j+"<"+a+">")}else{if(a<e){for(h=a;h<=e;h++){k.push(j+"<"+h+">")}}else{for(h=a;h>=e;h--){k.push(j+"<"+h+">")}}}}}else{k.push(d[c])}}return k},setImgPixel:function(f,d,l,k,j,c,e){var h=(d+l*f.width)*4;f.data[h]=k;f.data[h+1]=j;f.data[h+2]=c;f.data[h+3]=e},updateGraph:function(e,b){var h=e.eIOCan;var c=200;var a=16;var k;e.history.push(b);if(e.history.length>c){k=e.history.length-c;e.history=e.history.slice(k)}if(!cycle_sim.graphsEnabled){return}var l=h.getContext("2d");var d=l.createImageData(c,a);var j;var i;var g;var f=a>>1;for(i=0;i<a;i++){for(j=0;j<c;j++){if(j<e.history.length){g=e.history[j];if(g&&(i<=f)){cycle_sim.setImgPixel(d,j,i,0,0,0,255)}else{if(!g&&(i>f)){cycle_sim.setImgPixel(d,j,i,0,0,0,255)}else{cycle_sim.setImgPixel(d,j,i,255,255,255,255)}}}else{cycle_sim.setImgPixel(d,j,i,128,128,128,255)}}}l.putImageData(d,0,0)},parseNetlist:function(t){cycle_sim.log("===Netlist parse start.");cycle_sim.hw={};var u=t.toUpperCase();u=u.replace(/[ \t]{2,}/g," ");cycle_sim.log("Netlist is "+u.length+" bytes long.");if(u.length===0){cycle_sim.log("ERROR: Empty netlist");ga("send","event","cycle_sim","parse","FAIL-EmptyNetlist");return false}var h=u.split("\n");cycle_sim.log("Netlist is "+h.length+" lines long.");cycle_sim.clearIODiv();cycle_sim.clearHierDiv();var s;var v;var w;var n;var l;var x=false;var a;var q;var j;var g;var b;var k;var r;var m;var p;var f;var d;var e;var o;var c;cycle_sim.hw.signals=[];cycle_sim.hw.primitives=[];cycle_sim.hw.time=0;cycle_sim.hw.testStatus="PASS";cycle_sim.hw.blocks=cycle_sim_prim.getBlocks();for(v=0;v<h.length;v++){w=v+1;l=h[v];n=l.split("#")[0].trim();if(n.length>0){a=n.split(" ");q=a[0];if(x===true){switch(q){case"PORT":if(a.length!==3){cycle_sim.netlistErrorLog("PORT should be exactly 3 words",w,l);ga("send","event","cycle_sim","parse","FAIL-PortShouldBe3Words");return false}g=a[1];if(["IN","OUT"].indexOf(g)===-1){cycle_sim.netlistErrorLog('PORT direction must be either IN or OUT, not "'+g+'"',w,l);ga("send","event","cycle_sim","parse","FAIL-PortDirectionMustBeInOrOut");return false}b=a[2];o=cycle_sim.expandNet(b);for(s=0;s<o.length;s++){b=o[s];if(cycle_sim.findObjByProp(j.nets,"name",b)!==undefined){cycle_sim.netlistErrorLog("PORT must provide a unique name",w,l);ga("send","event","cycle_sim","parse","FAIL-PortMustProvideAUniqueName");return false}k={name:b,direction:g};j.ports.push(k);r={name:b,type:"port",portNum:j.ports.length-1};j.nets.push(r)}break;case"NET":if(a.length!==2){cycle_sim.netlistErrorLog("NET should be exactly 2 words",w,l);ga("send","event","cycle_sim","parse","FAIL-NetShouldBe2Words");return false}m=a[1];o=cycle_sim.expandNet(m);for(s=0;s<o.length;s++){m=o[s];if(cycle_sim.findObjByProp(j.nets,"name",m)!==undefined){cycle_sim.netlistErrorLog("NET must provide a unique name",w,l);ga("send","event","cycle_sim","parse","FAIL-NetMustBeUnique");return false}r={name:m,type:"net"};j.nets.push(r)}break;case"INST":if(a.length<4){cycle_sim.netlistErrorLog("INST must have at least 4 words",w,l);ga("send","event","cycle_sim","parse","FAIL-InstMustHave4Words");return false}f=a[1];p=a[2];if(cycle_sim.hw.blocks[p]===undefined){cycle_sim.netlistErrorLog("INST must only refer to previously defined blocks ("+p+")",w,l);ga("send","event","cycle_sim","parse","FAIL-InstMustReferToDefinedBlock");return false}e=a.slice(3);c=[];for(s=0;s<e.length;s++){c=c.concat(cycle_sim.expandNet(e[s]))}e=c;for(s=0;s<e.length;s++){if(cycle_sim.findObjByProp(j.nets,"name",e[s])===undefined){if((e[s]!=="TRUE")&&(e[s]!=="FALSE")){cycle_sim.netlistErrorLog("INST ports must only be connected to previously defined PORTS/NETS ("+e[s]+")",w,l);ga("send","event","cycle_sim","parse","FAIL-InstPortsMustConnectToDefined");return false}}}if(e.length!==cycle_sim.hw.blocks[p].ports.length){cycle_sim.netlistErrorLog("INST declaration must assign as many ports as a block actually has ("+e.length+" != "+cycle_sim.hw.blocks[p].ports.length+")",w,l);ga("send","event","cycle_sim","parse","FAIL-InstDeclarationPortCountMismatch");return false}d={name:f,blockName:p,ports:e,primitive:false};if(j.insts.filter(function(i){return i.name===f}).length>0){cycle_sim.netlistErrorLog("Each INST name must be unique in a given block. ("+f+")",w,l);ga("send","event","cycle_sim","parse","FAIL-InstNameMustBeUniqueInABlock");return false}j.insts.push(d);break;case"ENDDEF":if(a.length!==1){cycle_sim.netlistErrorLog("ENDDEF should be exactly 1 word",w,l);ga("send","event","cycle_sim","parse","FAIL-EnddefMustBe1Word");return false}if(x===false){cycle_sim.netlistErrorLog("ENDDEF should only occur after a valid DEF",w,l);ga("send","event","cycle_sim","parse","FAIL-EnddefMustComeAfterDef");return false}cycle_sim.hw.blocks[j.blockName]=j;cycle_sim.log("Parsed "+j.blockName);x=false;break;case"DEF":cycle_sim.netlistErrorLog("DEF not allowed inside previous DEF. ENDDEF should come first",w,l);ga("send","event","cycle_sim","parse","FAIL-DefNotAllowedInDef");return false;break;default:cycle_sim.netlistErrorLog('Unknown command "'+q+'"',w,l);ga("send","event","cycle_sim","parse","FAIL-UnknownCommand");return false}}else{if(q!=="DEF"){cycle_sim.netlistErrorLog("Expected DEF",w,l);ga("send","event","cycle_sim","parse","FAIL-ExpectedDef");return false}else{if(a.length!==2){cycle_sim.netlistErrorLog("DEF should be exactly 2 words",w,l);ga("send","event","cycle_sim","parse","FAIL-DefShouldBe2Words");return false}if(cycle_sim.hw.blocks[a[1]]!==undefined){cycle_sim.netlistErrorLog("DEF must not redefine previously defined blocks",w,l);ga("send","event","cycle_sim","parse","FAIL-DefMustNotRedefine");return false}j={blockName:a[1],ports:[],nets:[{name:"FALSE",type:"net"},{name:"TRUE",type:"net"}],insts:[]};x=true}}}}if(x===true){cycle_sim.netlistErrorLog("Last open DEF not closed with ENDDEF","EOF","");ga("send","event","cycle_sim","parse","FAIL-LastDEFNotClosed");return false}cycle_sim.log("===Netlist parse complete.");ga("send","event","cycle_sim","parse","PASS");return true},createNewSignal:function(){var a={value:false,next:false};cycle_sim.hw.signals.push(a);return(cycle_sim.hw.signals.length-1)},createInstance:function(l,n,c){var h={name:c};h.blockName=l;var m={};var e=cycle_sim.hw.blocks[l];var g;var k;for(g=0;g<e.nets.length;g++){if(e.nets[g].type==="net"){if(e.nets[g].name==="FALSE"){k=0}else{if(e.nets[g].name==="TRUE"){k=1}else{k=cycle_sim.createNewSignal()}}}else{k=n[e.nets[g].portNum]}m[e.nets[g].name]={name:e.nets[g].name,signal:k}}h.nets=m;h.insts=[];var b;var d;var f;var a;for(g=0;g<e.insts.length;g++){d=[];for(f=0;f<e.insts[g].ports.length;f++){a=m[e.insts[g].ports[f]].signal;d.push(a)}b=cycle_sim.createInstance(e.insts[g].blockName,d,c+":"+e.insts[g].name);h.insts.push(b)}if(e.primitive){e.init(h);cycle_sim.hw.primitives.push(h)}return h},printInstState:function(e,d){if(d===undefined){d=""}var b=e.name+"("+e.blockName+")";var c;var a=Object.keys(e.nets);var g;var f;for(c=0;c<a.length;c++){if(a[c]==="FALSE"||a[c]==="TRUE"){continue}g=cycle_sim.getSigVal(e,a[c]);if(g===undefined){f="U"}else{f=g?"T":"F"}b+=" "+e.nets[a[c]].name+"="+f+","}cycle_sim.log(d+b);for(c=0;c<e.insts.length;c++){cycle_sim.printInstState(e.insts[c],d+"-")}},printSingleInstState:function(g){var d;var e;var f;var b;var c;var a;if(g==="TOP"){d=cycle_sim.hw.simState}else{d=cycle_sim.hw.simState;e=g.split("_");for(b=1;b<e.length;b++){f=parseInt(e[b],10);d=d.insts[f]}}c=d.name+" ("+d.blockName+")";for(a in d.nets){if(a!=="TRUE"&&a!=="FALSE"){c+="\n"+a+"="+cycle_sim.getSigVal(d,a)}}cycle_sim.log(c)},clearIODiv:function(){cycle_sim.log("Clearing IO");var a=document.getElementById("div_design_io");a.innerHTML=""},clearHierDiv:function(){cycle_sim.log("Clearing Hierarchy");var a=document.getElementById("div_design_hierarchy");a.innerHTML=""},toggleHierarchy:function(c,k){var h;var l;var e;var d;var b;var m;var a;var f;var g;var j;if(c==="TOP"){h=cycle_sim.hw.simState}else{h=cycle_sim.hw.simState;m=c.split("_");for(f=1;f<m.length;f++){a=parseInt(m[f],10);h=h.insts[a]}}l="span_design_hier_"+c;e=document.getElementById(l);d='<button type="button" onclick="cycle_sim.toggleHierarchy(\''+c+"','"+k+"');\">";if(e.childElementCount<=2){d+='-</button><button type="button" onclick="cycle_sim.printSingleInstState(\''+c+"')\">Print</button>"+k;if(h.insts.length>0){d+="<ul>";for(f=0;f<h.insts.length;f++){b=c+"_"+f;g=h.insts[f].name+" ("+h.insts[f].blockName+")";d+="<li>";j='<button type="button" onclick="cycle_sim.printSingleInstState(\''+b+"')\">Print</button>";if(cycle_sim.hw.blocks[h.insts[f].blockName].primitive===true){d+='<span id="span_design_hier_'+b+'"><button type="button" disabled="disabled">p</button>'+j+g+"</span>"}else{d+='<span id="span_design_hier_'+b+'"><button type="button" onclick="cycle_sim.toggleHierarchy(\''+b+"','"+g+"')\">+</button> "+j+g+"</span>"}d+="</li>"}d+="</ul>"}}else{d+='+</button><button type="button" onclick="cycle_sim.printSingleInstState(\''+c+"')\">Print</button>"+k}e.innerHTML=d},elaborate:function(){cycle_sim.log("===Elaboration start.");if(cycle_sim.hw.blocks.TOP===undefined){cycle_sim.log("ERROR: A block named TOP must be defined");ga("send","event","cycle_sim","elaborate","FAIL-TopMustBeDefined");return false}if(cycle_sim.hw.blocks.TOP.ports.length>0){cycle_sim.log("ERROR: The TOP block must have no ports");ga("send","event","cycle_sim","elaborate","FAIL-TopMustNotHavePorts");return false}cycle_sim.clearIODiv();cycle_sim.hw.primitives=[];cycle_sim.hw.signals=[];cycle_sim.hw.signals.push({value:false,next:false});cycle_sim.hw.signals.push({value:true,next:true});cycle_sim.hw.simState=cycle_sim.createInstance("TOP",[],"TOP");cycle_sim.nandCount=cycle_sim.hw.primitives.filter(function(b){return b.blockName==="NAND"}).length;cycle_sim.log("Used "+cycle_sim.nandCount+" NANDs.");cycle_sim.hw.time=0;cycle_sim.eSimTime.textContent=cycle_sim.hw.time;var a=document.getElementById("div_design_hierarchy");a.innerHTML='<ul><li><span id="span_design_hier_TOP"><button type="button" onclick="cycle_sim.toggleHierarchy(\'TOP\',\'TOP (TOP)\')">+</button><button type="button" onclick="cycle_sim.printSingleInstState(\'TOP\')">Print</button> TOP (TOP) </span></li></ul>';cycle_sim.log("===Elaboration end.");ga("send","event","cycle_sim","elaborate","PASS");return true},simTick:function(){var a;var c;cycle_sim.eSimTime.textContent=cycle_sim.hw.time;var b;for(b=0;b<cycle_sim.simTickIterations;b++){for(a=0;a<cycle_sim.hw.primitives.length;a++){c=cycle_sim.hw.primitives[a];cycle_sim.hw.blocks[c.blockName].tick(c)}for(a=0;a<cycle_sim.hw.signals.length;a++){cycle_sim.hw.signals[a].value=cycle_sim.hw.signals[a].next}cycle_sim.hw.time+=1;if(cycle_sim.intervalID===undefined){ga("send","event","cycle_sim","step");break}}if((cycle_sim.simCyclesPerSecond!==cycle_sim.currentCyclesPerSecond)&&(cycle_sim.intervalID!==undefined)){cycle_sim.simPause();cycle_sim.simRun()}},simRun:function(){if(cycle_sim.intervalID===undefined){if(cycle_sim.hw.simState!==undefined){cycle_sim.currentCyclesPerSecond=cycle_sim.simCyclesPerSecond;cycle_sim.intervalID=setInterval(cycle_sim.simTick,1000/cycle_sim.simCyclesPerSecond);ga("send","event","cycle_sim","run","click")}else{cycle_sim.log("ERROR: You can not run until you have compiled/elaborated successfully with the Init\\Reset button.")}}},simPause:function(){if(cycle_sim.intervalID!==undefined){clearInterval(cycle_sim.intervalID);cycle_sim.intervalID=undefined;cycle_sim.eSimTime.textContent=cycle_sim.hw.time;ga("send","event","cycle_sim","pause","click")}},changeSimSpeed:function(b){if(b==="+"){cycle_sim.speedIndex=cycle_sim.speedIndex+1}else{cycle_sim.speedIndex=cycle_sim.speedIndex-1}if(cycle_sim.speedIndex<0){cycle_sim.speedIndex=0}if(cycle_sim.speedIndex>=cycle_sim.speedList.length){cycle_sim.speedIndex=cycle_sim.speedList.length-1}if(cycle_sim.speedIndex===cycle_sim.speedList.length-1){cycle_sim.speedMax=true;cycle_sim.simTickIterations=100}else{cycle_sim.speedMax=false;cycle_sim.simTickIterations=1}cycle_sim.simCyclesPerSecond=cycle_sim.speedList[cycle_sim.speedIndex];var a=document.getElementById("span_design_speed");a.textContent=cycle_sim.speedNames[cycle_sim.speedIndex];ga("send","event","cycle_sim","change_speed",cycle_sim.speedIndex)},reset:function(a){var b=document.getElementById(a);return cycle_sim.parseNetlist(b.value)&&cycle_sim.elaborate()},initialize:function(){cycle_sim.eSimTime=document.getElementById("span_design_time")}};