improve load sequencing, add layer choosing, link to python sim, add keyboard tips, add example nmi test, tweak navbuttons, enhance chipstatus output

This commit is contained in:
BigEd 2010-09-18 17:46:24 +00:00
parent 0ecb753ec6
commit d032580201
4 changed files with 179 additions and 31 deletions

View File

@ -21,6 +21,8 @@
*/ */
var ctrace = false; var ctrace = false;
var noGraphics = false;
var loglevel = 3;
var ridx = 0; var ridx = 0;
function recalcNodeList(list){ function recalcNodeList(list){

View File

@ -8,12 +8,26 @@
<script src="nodenames.js"></script> <script src="nodenames.js"></script>
<script src="wires.js"></script> <script src="wires.js"></script>
<script src="chipsim.js"></script> <script src="chipsim.js"></script>
<br>
<script src="memtable.js"></script> <script src="memtable.js"></script>
<script src="macros.js"></script> <script src="macros.js"></script>
</head> </head>
<body onload="setup();"> <body onload="setTimeout(setup,200)">
<p class="title">The 6502</p> <br />
<span id="title"><a href="/">The Visual 6502</a></span><br /><br />
<span id="plain">
If the chip does not load, try another browser: Chrome, Safari, or Firefox
<br />
<br />
Hit '>' to zoom in, '<' to zoom out
<br />
Right-click to scroll around
<br />
Enter your own program into the array of RAM
<br />
<br />
</span>
<div class="frame" id="frame"> <div class="frame" id="frame">
<div class="chip"> <div class="chip">
<canvas class="chip" id="chipbg"></canvas> <canvas class="chip" id="chipbg"></canvas>
@ -22,15 +36,30 @@
<canvas class="chip" id="hitbuffer"></canvas> <canvas class="chip" id="hitbuffer"></canvas>
</div> </div>
<div class = "buttons"> <div class = "buttons">
<a href ="javascript:stopChip()"id="stop"><img class="navstop" src="images/stop.png"></a> <div style="position:relative; float:left;">
<a href ="javascript:runChip()" id="start"><img class="navplay" src="images/play.png"></a> <a href ="javascript:stopChip()"id="stop"><img class="navstop" src="images/stop.png"></a>
<a href ="javascript:resetChip()"><img class="navbutton" src="images/up.png"></a> <a href ="javascript:runChip()" id="start"><img class="navplay" src="images/play.png"></a>
<a href ="javascript:stepBack()"><img class="navbutton" src="images/prev.png"></a> </div>
<a href ="javascript:stepForward()"><img class="navbutton" src="images/next.png"></a> <div style="float:left;">
<a href ="javascript:resetChip()"><img class="navbutton" src="images/up.png"></a>
<a href ="javascript:stepBack()"><img class="navbutton" src="images/prev.png"></a>
<a href ="javascript:stepForward()"><img class="navbutton" src="images/next.png"></a>
</div>
</div> </div>
<p class="status" id="status">x: 0<br>y: 0</p> <p class="status" id="status">x: 0<br>y: 0</p>
<table class="memtable" id="memtable"></table> <table class="memtable" id="memtable"></table>
</div> </div>
<div id="updateShow"> Show:
<input type="checkbox" name="0" id="updateShow0" onchange="updateShow(this.name,this.checked)" />(metal)
<input type="checkbox" name="1" id="updateShow1" onchange="updateShow(this.name,this.checked)" />(diff)
<input type="checkbox" name="2" id="updateShow2" onchange="updateShow(this.name,this.checked)" />(diode)
<input type="checkbox" name="3" id="updateShow3" onchange="updateShow(this.name,this.checked)" />(diff0)
<input type="checkbox" name="4" id="updateShow4" onchange="updateShow(this.name,this.checked)" />(diff1)
<input type="checkbox" name="5" id="updateShow5" onchange="updateShow(this.name,this.checked)" />(poly)
</div>
<br />
<br />
In addition to this JavaScript project, see our <a href="../python6502.html">Python-based simulator</a> which may be easier to customize, verify, and apply to the study of long programs.<br />
<br />
</body> </body>
</html> </html>

119
macros.js
View File

@ -39,11 +39,55 @@ function go(n){
} }
function steps(){ function steps(){
if(running) step(); if(running) {
setTimeout(steps, 200); step();
setTimeout(steps, 0); // schedule the next poll
}
} }
function testNMI(n){
initChip();
mWrite(0x0000, 0x38); // set carry
mWrite(0x0001, 0x4c); // jump to test code
mWrite(0x0002, 0x06);
mWrite(0x0003, 0x23);
mWrite(0x22ff, 0x38); // set carry
mWrite(0x2300, 0xea);
mWrite(0x2301, 0xea);
mWrite(0x2302, 0xea);
mWrite(0x2303, 0xea);
mWrite(0x2304, 0xb0); // branch carry set to self
mWrite(0x2305, 0xfe);
mWrite(0x2306, 0xb0); // branch carry set to self
mWrite(0x2307, 0x01);
mWrite(0x2308, 0x00); // brk should be skipped
mWrite(0x2309, 0xa9); // anything
mWrite(0x230a, 0xde); // anything
mWrite(0x230b, 0xb0); // branch back with page crossing
mWrite(0x230c, 0xf2);
mWrite(0xc018, 0x40); // nmi handler
mWrite(0xfffa, 0x18); // nmi vector
mWrite(0xfffb, 0xc0);
mWrite(0xfffc, 0x00); // reset vector
mWrite(0xfffd, 0x00);
for(var i=0;i<n;i++){step();}
setLow('nmi');
chipStatus();
for(var i=0;i<8;i++){step();}
setHigh('nmi');
chipStatus();
for(var i=0;i<16;i++){step();}
}
function initChip(){ function initChip(){
var start = now();
for(var nn in nodes) nodes[nn].state = 'fl'; for(var nn in nodes) nodes[nn].state = 'fl';
nodes[ngnd].state = 'gnd'; nodes[ngnd].state = 'gnd';
nodes[npwr].state = 'vcc'; nodes[npwr].state = 'vcc';
@ -60,6 +104,7 @@ function initChip(){
cycle = 0; cycle = 0;
trace = Array(); trace = Array();
chipStatus(); chipStatus();
console.log('initChip done after', now()-start);
} }
function step(){ function step(){
@ -78,11 +123,10 @@ function halfStep(){
function resetStep(){ function resetStep(){
var clk = isNodeHigh(nodenames['clk0']); var clk = isNodeHigh(nodenames['clk0']);
if (clk) {setLow('clk0'); handleBusRead(); } if (clk) {setLow('clk0'); handleBusRead(); }
else {setHigh('clk0'); handleBusWrite();} else {setHigh('clk0'); handleBusWrite();}
} }
function handleBusRead(){ function handleBusRead(){
if(isNodeHigh(nodenames['rw'])) writeDataBus(mRead(readAddressBus())); if(isNodeHigh(nodenames['rw'])) writeDataBus(mRead(readAddressBus()));
} }
@ -102,8 +146,26 @@ function readA(){return readBits('a', 8);}
function readY(){return readBits('y', 8);} function readY(){return readBits('y', 8);}
function readX(){return readBits('x', 8);} function readX(){return readBits('x', 8);}
function readP(){return readBits('p', 8);} function readP(){return readBits('p', 8);}
function readPstring(){
var result;
result = (isNodeHigh(nodenames['p7'])?'N':'n') +
(isNodeHigh(nodenames['p6'])?'V':'v') +
'-' +
(isNodeHigh(nodenames['p3'])?'B':'b') +
(isNodeHigh(nodenames['p3'])?'D':'d') +
(isNodeHigh(nodenames['p2'])?'I':'i') +
(isNodeHigh(nodenames['p1'])?'Z':'z') +
(isNodeHigh(nodenames['p0'])?'C':'c');
return result;
}
function readSP(){return readBits('s', 8);} function readSP(){return readBits('s', 8);}
function readPC(){return (readBits('pch', 8)<<8) + readBits('pcl', 8);}
function readPCL(){return readBits('pcl', 8);}
function readPCH(){return readBits('pch', 8);}
function readBit(name){
return isNodeHigh(nodenames[name])?1:0;
}
function readBits(name, n){ function readBits(name, n){
var res = 0; var res = 0;
for(var i=0;i<n;i++){ for(var i=0;i<n;i++){
@ -151,6 +213,7 @@ function runChip(){
start.style.visibility = 'hidden'; start.style.visibility = 'hidden';
stop.style.visibility = 'visible'; stop.style.visibility = 'visible';
running = true; running = true;
steps();
} }
function stopChip(){ function stopChip(){
@ -163,7 +226,8 @@ function stopChip(){
function resetChip(){ function resetChip(){
stopChip(); stopChip();
initChip(); setStatus('resetting 6502...');
setTimeout(initChip,0);
} }
function stepForward(){ function stepForward(){
@ -181,17 +245,40 @@ function stepBack(){
} }
function chipStatus(){ function chipStatus(){
var pc = readAddressBus(); var ab = readAddressBus();
setStatus('PC:', hexWord(pc), var machine1 =
'D:', hexByte(readDataBus()), ' halfcyc:' + cycle +
'SP:',hexByte(readSP()), ' phi0:' + readBit('clk0') +
'cycle:', cycle, '<br>', ' AB:' + hexWord(ab) +
'A:', hexByte(readA()), ' D:' + hexByte(readDataBus()) +
'X:', hexByte(readX()), ' RnW:' + readBit('rw');
'Y:', hexByte(readY()), var machine2 =
'P:', hexByte(readP()) ' PC:' + hexWord(readPC()) +
); ' A:' + hexByte(readA()) +
selectCell(pc); ' X:' + hexByte(readX()) +
' Y:' + hexByte(readY()) +
' SP:' + hexByte(readSP()) +
' ' + readPstring();
var machine3 =
' Sync:' + readBit('sync')
' IRQ:' + readBit('irq') +
' NMI:' + readBit('nmi');
var machine4 =
' IR:' + hexByte(255 - readBits('notir', 8)) +
' idl:' + hexByte(255 - readBits('idl', 8)) +
' alu:' + hexByte(255 - readBits('alu', 8)) +
' TCstate:' + readBit('clock1') + readBit('clock2') +
readBit('t2') + readBit('t3') + readBit('t4') + readBit('t5');
var machine5 =
' notRdy0:' + readBit('notRdy0') +
' fetch:' + readBit('fetch') +
' clearIR:' + readBit('clearIR') +
' D1x1:' + readBit('D1x1');
setStatus(machine1 + "<br>" + machine2);
if (loglevel>2) {
console.log(machine1 + " " + machine2 + " " + machine3 + " " + machine4 + " " + machine5);
}
selectCell(ab);
} }
function getMem(){ function getMem(){

View File

@ -26,8 +26,10 @@ var zoom=1;
var dragMouseX, dragMouseY, moved; var dragMouseX, dragMouseY, moved;
var statbox; var statbox;
var colors = ['rgba(128,128,128,0.4)','#FFFF00','#FF00FF','#4DFF4D', var layernames = ['metal', 'diff', 'inputdiode', 'diff0', 'diff1', 'poly'];
var colors = ['rgba(128,128,192,0.4)','#FFFF00','#FF00FF','#4DFF4D',
'#FF4D4D','#801AC0','rgba(128,0,255,0.75)']; '#FF4D4D','#801AC0','rgba(128,0,255,0.75)'];
var drawlayers = [true, true, false, false, false, false];
var nodes = new Array(); var nodes = new Array();
var transistors = {}; var transistors = {};
@ -42,11 +44,19 @@ var npwr = nodenames['vcc'];
// //
///////////////////////// /////////////////////////
// try to present a meaningful page before starting expensive work
function setup(){ function setup(){
statbox = document.getElementById('status');
setStatus('loading 6502...');
setTimeout(setup_part2, 0);
}
function setup_part2(){
frame = document.getElementById('frame'); frame = document.getElementById('frame');
statbox = document.getElementById('status'); statbox = document.getElementById('status');
setupNodes(); setupNodes();
setupTransistors(); setupTransistors();
setupLayerVisibility();
setupBackground(); setupBackground();
setupOverlay(); setupOverlay();
setupHilite(); setupHilite();
@ -56,6 +66,11 @@ function setup(){
setupTable(); setupTable();
window.onkeypress = function(e){handleKey(e);} window.onkeypress = function(e){handleKey(e);}
hilite.onmousedown = function(e){mouseDown(e);} hilite.onmousedown = function(e){mouseDown(e);}
setStatus('resetting 6502...');
setTimeout(setup_part3, 0);
}
function setup_part3(){
initChip(); initChip();
document.getElementById('stop').style.visibility = 'hidden'; document.getElementById('stop').style.visibility = 'hidden';
go(); go();
@ -89,8 +104,17 @@ function setupTransistors(){
} }
} }
function setupLayerVisibility(){
var x=document.getElementById('updateShow');
for (var i=0;i<x.childNodes.length;i++) {
if(x.childNodes[i].type='checkbox'){
x.childNodes[i].checked=drawlayers[x.childNodes[i].name];
}
}
}
function setupBackground(){ function setupBackground(){
console.log('starting setupBackground');
chipbg = document.getElementById('chipbg'); chipbg = document.getElementById('chipbg');
chipbg.width = 4000; chipbg.width = 4000;
chipbg.height = 4000; chipbg.height = 4000;
@ -100,16 +124,16 @@ function setupBackground(){
ctx.strokeStyle = 'rgba(255,255,255,0.5)'; ctx.strokeStyle = 'rgba(255,255,255,0.5)';
ctx.lineWidth = 4; ctx.lineWidth = 4;
ctx.fillRect(0,0,10000,10000); ctx.fillRect(0,0,10000,10000);
var start = now();
for(var i in segdefs){ for(var i in segdefs){
var seg = segdefs[i]; var seg = segdefs[i];
var c = seg[2]; var c = seg[2];
ctx.fillStyle = colors[c]; if (drawlayers[c]) {
drawSeg(ctx, segdefs[i].slice(3)); ctx.fillStyle = colors[c];
ctx.fill(); drawSeg(ctx, segdefs[i].slice(3));
if((c==0)||(c==6)) ctx.stroke(); ctx.fill();
if((c==0)||(c==6)) ctx.stroke();
}
} }
// console.log('time to draw: ', now() - start, ' ms');
} }
function setupOverlay(){ function setupOverlay(){
@ -189,6 +213,7 @@ function hiliteNode(n){
function drawSeg(ctx, seg){ function drawSeg(ctx, seg){
if(noGraphics) return;
var dx = 400; var dx = 400;
ctx.beginPath(); ctx.beginPath();
ctx.moveTo(seg[0]+dx, 10000-seg[1]) ctx.moveTo(seg[0]+dx, 10000-seg[1])
@ -288,6 +313,11 @@ function findNodeNumber(x,y){
return (high<<8)+(mid<<4)+low; return (high<<8)+(mid<<4)+low;
} }
function updateShow(layer, on){
drawlayers[layer]=on;
setupBackground();
}
///////////////////////// /////////////////////////
// //
// Etc. // Etc.