Initial checking of chip-z80

This commit is contained in:
David Banks 2018-09-19 13:24:49 +01:00
parent 0a6866f10c
commit 7a0cb72539
6 changed files with 11130 additions and 0 deletions

278
chip-z80/nodenames.js Normal file
View File

@ -0,0 +1,278 @@
var nodenames ={
vss: 1,
vcc: 2,
clk: 3,
ab0: 5,
ab1: 6,
ab2: 7,
ab3: 8,
ab4: 9,
ab5: 10,
ab6: 11,
ab7: 12,
ab8: 13,
ab9: 14,
ab10: 15,
ab11: 16,
ab12: 17,
ab13: 18,
ab14: 19,
ab15: 20,
_reset: 21,
_wait: 22,
_int: 23,
_nmi: 24,
_busrq: 25,
_m1: 26,
_rd: 27,
_wr: 28,
_mreq: 29,
_iorq: 30,
_rfsh: 31,
db0: 32,
db1: 33,
db2: 34,
db3: 35,
db4: 36,
db5: 37,
db6: 38,
db7: 39,
_halt: 40,
_busak: 41,
t1: 115,
t2: 137,
t3: 144,
t4: 166,
t5: 134,
t6: 168,
m1: 155,
m2: 173,
m3: 163,
m4: 159,
m5: 209,
m6: 210,
reg_a0: 2271,
reg_f0: 1854,
reg_b0: 2268,
reg_c0: 1851,
reg_d0: 2264,
reg_e0: 1847,
reg_h0: 2266,
reg_l0: 1849,
reg_w0: 2260,
reg_z0: 1843,
reg_pch0: 2258,
reg_pcl0: 1841,
reg_sph0: 2261,
reg_spl0: 1844,
reg_ixh0: 2263,
reg_ixl0: 1846,
reg_iyh0: 2262,
reg_iyl0: 1845,
reg_i0: 2259,
reg_r0: 1842,
reg_aa0: 2270,
reg_ff0: 1853,
reg_bb0: 2269,
reg_cc0: 1852,
reg_dd0: 2265,
reg_ee0: 1848,
reg_hh0: 2267,
reg_ll0: 1850,
reg_a1: 2296,
reg_f1: 1881,
reg_b1: 2293,
reg_c1: 1878,
reg_d1: 2289,
reg_e1: 1874,
reg_h1: 2291,
reg_l1: 1876,
reg_w1: 2285,
reg_z1: 1870,
reg_pch1: 2283,
reg_pcl1: 1868,
reg_sph1: 2286,
reg_spl1: 1871,
reg_ixh1: 2288,
reg_ixl1: 1873,
reg_iyh1: 2287,
reg_iyl1: 1872,
reg_i1: 2284,
reg_r1: 1869,
reg_aa1: 2295,
reg_ff1: 1880,
reg_bb1: 2294,
reg_cc1: 1879,
reg_dd1: 2290,
reg_ee1: 1875,
reg_hh1: 2292,
reg_ll1: 1877,
reg_a2: 2384,
reg_f2: 1958,
reg_b2: 2381,
reg_c2: 1955,
reg_d2: 2377,
reg_e2: 1951,
reg_h2: 2379,
reg_l2: 1953,
reg_w2: 2373,
reg_z2: 1947,
reg_pch2: 2371,
reg_pcl2: 1945,
reg_sph2: 2374,
reg_spl2: 1948,
reg_ixh2: 2376,
reg_ixl2: 1950,
reg_iyh2: 2375,
reg_iyl2: 1949,
reg_i2: 2372,
reg_r2: 1946,
reg_aa2: 2383,
reg_ff2: 1957,
reg_bb2: 2382,
reg_cc2: 1956,
reg_dd2: 2378,
reg_ee2: 1952,
reg_hh2: 2380,
reg_ll2: 1954,
reg_a3: 2416,
reg_f3: 1986,
reg_b3: 2413,
reg_c3: 1983,
reg_d3: 2409,
reg_e3: 1979,
reg_h3: 2411,
reg_l3: 1981,
reg_w3: 2405,
reg_z3: 1975,
reg_pch3: 2403,
reg_pcl3: 1973,
reg_sph3: 2406,
reg_spl3: 1976,
reg_ixh3: 2408,
reg_ixl3: 1978,
reg_iyh3: 2407,
reg_iyl3: 1977,
reg_i3: 2404,
reg_r3: 1974,
reg_aa3: 2415,
reg_ff3: 1985,
reg_bb3: 2414,
reg_cc3: 1984,
reg_dd3: 2410,
reg_ee3: 1980,
reg_hh3: 2412,
reg_ll3: 1982,
reg_a4: 2489,
reg_f4: 2058,
reg_b4: 2486,
reg_c4: 2055,
reg_d4: 2482,
reg_e4: 2051,
reg_h4: 2484,
reg_l4: 2053,
reg_w4: 2478,
reg_z4: 2047,
reg_pch4: 2476,
reg_pcl4: 2045,
reg_sph4: 2479,
reg_spl4: 2048,
reg_ixh4: 2481,
reg_ixl4: 2050,
reg_iyh4: 2480,
reg_iyl4: 2049,
reg_i4: 2477,
reg_r4: 2046,
reg_aa4: 2488,
reg_ff4: 2057,
reg_bb4: 2487,
reg_cc4: 2056,
reg_dd4: 2483,
reg_ee4: 2052,
reg_hh4: 2485,
reg_ll4: 2054,
reg_a5: 2527,
reg_f5: 2082,
reg_b5: 2524,
reg_c5: 2079,
reg_d5: 2520,
reg_e5: 2075,
reg_h5: 2522,
reg_l5: 2077,
reg_w5: 2516,
reg_z5: 2071,
reg_pch5: 2514,
reg_pcl5: 2069,
reg_sph5: 2517,
reg_spl5: 2072,
reg_ixh5: 2519,
reg_ixl5: 2074,
reg_iyh5: 2518,
reg_iyl5: 2073,
reg_i5: 2515,
reg_r5: 2070,
reg_aa5: 2526,
reg_ff5: 2081,
reg_bb5: 2525,
reg_cc5: 2080,
reg_dd5: 2521,
reg_ee5: 2076,
reg_hh5: 2523,
reg_ll5: 2078,
reg_a6: 2610,
reg_f6: 2155,
reg_b6: 2607,
reg_c6: 2152,
reg_d6: 2603,
reg_e6: 2148,
reg_h6: 2605,
reg_l6: 2150,
reg_w6: 2599,
reg_z6: 2144,
reg_pch6: 2597,
reg_pcl6: 2142,
reg_sph6: 2600,
reg_spl6: 2145,
reg_ixh6: 2602,
reg_ixl6: 2147,
reg_iyh6: 2601,
reg_iyl6: 2146,
reg_i6: 2598,
reg_r6: 2143,
reg_aa6: 2609,
reg_ff6: 2154,
reg_bb6: 2608,
reg_cc6: 2153,
reg_dd6: 2604,
reg_ee6: 2149,
reg_hh6: 2606,
reg_ll6: 2151,
reg_a7: 2633,
reg_f7: 2179,
reg_b7: 2630,
reg_c7: 2176,
reg_d7: 2626,
reg_e7: 2172,
reg_h7: 2628,
reg_l7: 2174,
reg_w7: 2622,
reg_z7: 2168,
reg_pch7: 2620,
reg_pcl7: 2166,
reg_sph7: 2623,
reg_spl7: 2169,
reg_ixh7: 2625,
reg_ixl7: 2171,
reg_iyh7: 2624,
reg_iyl7: 2170,
reg_i7: 2621,
reg_r7: 2167,
reg_aa7: 2632,
reg_ff7: 2178,
reg_bb7: 2631,
reg_cc7: 2177,
reg_dd7: 2627,
reg_ee7: 2173,
reg_hh7: 2629,
reg_ll7: 2175,
}

3601
chip-z80/segdefs.js Normal file

File diff suppressed because it is too large Load Diff

258
chip-z80/support.js Normal file
View File

@ -0,0 +1,258 @@
// chip-specific support functions
//
// may override function definitions made previously
chipname='z80';
// DMB: Update this
grChipSize=7000;
ngnd = nodenames['vss'];
npwr = nodenames['vcc'];
nodenamereset = '_reset';
presetLogLists=[
['cycle',],
['ab','db','_m1','_rd','_wr','_mreq','_iorq','pc'],
['af', 'bc', 'de', 'hl', 'ix', 'iy', 'sp'],
['State'],
['_int','_nmi',nodenamereset],
];
function setupTransistors(){
for(i in transdefs){
var tdef = transdefs[i];
var name = tdef[0];
var gate = tdef[1];
var c1 = tdef[2];
var c2 = tdef[3];
var bb = tdef[4];
if(tdef[6])
// just ignore all the 'weak' transistors for now
continue;
if(c1==ngnd) {c1=c2;c2=ngnd;}
if(c1==npwr) {c1=c2;c2=npwr;}
var trans = {name: name, on: false, gate: gate, c1: c1, c2: c2, bb: bb};
nodes[gate].gates.push(trans);
nodes[c1].c1c2s.push(trans);
nodes[c2].c1c2s.push(trans);
transistors[name] = trans;
}
}
// simulate a single clock phase with no update to graphics or trace
function halfStep(){
var clk = isNodeHigh(nodenames['clk']);
eval(clockTriggers[cycle]);
if (clk) {setLow('clk'); }
else {setHigh('clk'); }
// DMB: It's almost certainly wrong to execute the on both clock edges
handleBusRead();
handleBusWrite;
}
function goUntilSyncOrWrite(){
halfStep();
cycle++;
while(
!isNodeHigh(nodenames['clk']) ||
( isNodeHigh(nodenames['_m1']) && isNodeHigh(nodenames['_wr']) )
) {
halfStep();
cycle++;
}
chipStatus();
}
function initChip(){
var start = now();
for(var nn in nodes) {
nodes[nn].state = false;
nodes[nn].float = true;
}
nodes[ngnd].state = false;
nodes[ngnd].float = false;
nodes[npwr].state = true;
nodes[npwr].float = false;
for(var tn in transistors) transistors[tn].on = false;
setLow(nodenamereset);
setLow('clk');
setHigh('_busrq');
setHigh('_int');
setHigh('_nmi');
setHigh('_wait');
recalcNodeList(allNodes());
// DMB: Not sure why the 6800 sim did something like this
//for(var i=0;i<8;i++){
// setHigh('clk');
// setLow('clk');
//}
for(var i=0;i<31;i++){halfStep();} // avoid updating graphics and trace buffer before user code
setHigh(nodenamereset);
refresh();
cycle = 0;
trace = Array();
if(typeof expertMode != "undefined")
updateLogList();
chipStatus();
if(ctrace)console.log('initChip done after', now()-start);
}
function handleBusRead(){
if(!isNodeHigh(nodenames['_rd'])){
var a = readAddressBus();
var d = eval(readTriggers[a]);
if(d == undefined)
d = mRead(readAddressBus());
if(!isNodeHigh(nodenames['_m1']))
eval(fetchTriggers[d]);
writeDataBus(d);
}
}
function handleBusWrite(){
if(!isNodeHigh(nodenames['_wr'])){
var a = readAddressBus();
var d = readDataBus();
eval(writeTriggers[a]);
mWrite(a,d);
if(a<0x200) setCellValue(a,d);
}
}
function readA(){return 0xFF ^ readBits('reg_a', 8);}
function readF(){return 0xFF ^ readBits('reg_f', 8);}
function readB(){return 0xFF ^ readBits('reg_b', 8);}
function readC(){return 0xFF ^ readBits('reg_c', 8);}
function readD(){return 0xFF ^ readBits('reg_d', 8);}
function readE(){return 0xFF ^ readBits('reg_e', 8);}
function readH(){return 0xFF ^ readBits('reg_h', 8);}
function readL(){return 0xFF ^ readBits('reg_l', 8);}
function readIX(){return 0xFFFF ^ ((readBits('reg_ixh', 8)<<8) + readBits('reg_ixl', 8));}
function readIY(){return 0xFFFF ^ ((readBits('reg_iyh', 8)<<8) + readBits('reg_iyl', 8));}
function readSP(){return 0xFFFF ^ ((readBits('reg_sph', 8)<<8) + readBits('reg_spl', 8));}
function readPC(){return 0xFFFF ^ ((readBits('reg_pch', 8)<<8) + readBits('reg_pcl', 8));}
function readPCL(){return 0xFF ^ readBits('reg_pcl', 8);}
function readPCH(){return 0xFF ^ readBits('reg_pch', 8);}
// The 6800 state control is something like a branching shift register
// ... but not quite like that
TCStates=[
"m1", "m2", "m3", "m4", "m5",
"t1", "t2", "t3", "t4", "t5", "t6",
];
function listActiveTCStates() {
var s=[];
for(var i=0;i<TCStates.length;i++){
var t=TCStates[i];
if (isNodeHigh(nodenames[t])) s.push(t.slice(0,3));
}
return s.join(" ");
}
function busToHexInv(busname){
var value=busToHex(busname)
if (typeof value != "undefined")
return value.replace(/./g,function(x){return (15-parseInt(x,16)).toString(16)});
else
return undefined;;
}
function busToString(busname){
// takes a signal name or prefix
// returns an appropriate string representation
// some 'signal names' are CPU-specific aliases to user-friendly string output
if(busname=='cycle')
return cycle>>1;
if(busname=='af')
return busToHexInv('reg_a') + busToHexInv('reg_f');
if(busname=='bc')
return busToHexInv('reg_b') + busToHexInv('reg_c');
if(busname=='de')
return busToHexInv('reg_d') + busToHexInv('reg_e');
if(busname=='hl')
return busToHexInv('reg_h') + busToHexInv('reg_l');
if(busname=='pc')
return busToHexInv('reg_pch') + busToHexInv('reg_pcl');
if(busname=='sp')
return busToHexInv('reg_sph') + busToHexInv('reg_spl');
if(busname=='ix')
return busToHexInv('reg_ixh') + busToHexInv('reg_ixl');
if(busname=='iy')
return busToHexInv('reg_iyh') + busToHexInv('reg_iyl');
if(busname=='State')
return listActiveTCStates();
// DMB: TODO
// if(busname=='Execute')
// return disassemblytoHTML(readBits('ir',8));
// if(busname=='Fetch')
// return !isNodeHigh(nodenames['_m1'])?disassemblytoHTML(readDataBus()):"";
// if(busname=='plaOutputs')
// // PLA outputs are mostly ^op- but some have a prefix too
// // - we'll allow the x and xx prefix but ignore the #
// return listActiveSignals('^([x]?x-)?op-');
// if(busname=='DPControl')
// return listActiveSignals('^dpc[0-9]+_');
if(busname[0]=="-"){
// invert the value of the bus for display
var value=busToHex(busname.slice(1))
if(typeof value != "undefined")
return value.replace(/./g,function(x){return (15-parseInt(x,16)).toString(16)});
else
return undefined;;
} else {
return busToHex(busname);
}
}
function chipStatus(){
var ab = readAddressBus();
var machine1 =
' halfcyc:' + cycle +
' clk:' + readBit('clk') +
' AB:' + hexWord(ab) +
' D:' + hexByte(readDataBus()) +
' M1:' + readBit('_m1') +
' RD:' + readBit('_rd') +
' WR:' + readBit('_wr') +
' MREQ:' + readBit('_mreq') +
' IORQ:' + readBit('_iorq');
var machine2 =
' PC:' + hexWord(readPC()) +
' A:' + hexByte(readA()) +
' F:' + hexByte(readF()) +
' B:' + hexByte(readB()) +
' C:' + hexByte(readC()) +
' D:' + hexByte(readD()) +
' E:' + hexByte(readE()) +
' H:' + hexByte(readH()) +
' L:' + hexByte(readL()) +
' IX:' + hexWord(readIX()) +
' IY:' + hexWord(readIY()) +
' SP:' + hexWord(readSP());
var machine3 =
'State: ' + busToString('State') +
'Hz: ' + estimatedHz().toFixed(1);
if(typeof expertMode != "undefined") {
machine3 += ' Exec: ' + busToString('Execute'); // no T-state info for 6800 yet
if(!isNodeHigh(nodenames['_m1']))
machine3 += ' (Fetch: ' + busToString('Fetch') + ')';
if(goldenChecksum != undefined)
machine3 += " Chk:" + traceChecksum + ((traceChecksum==goldenChecksum)?" OK":" no match");
}
setStatus(machine1, machine2, machine3);
if (logThese.length>1) {
updateLogbox(logThese);
}
selectCell(ab);
}
// DMB: TODO
var disassembly={
0x00: "nop",
};

26
chip-z80/testprogram.js Normal file
View File

@ -0,0 +1,26 @@
// This file testprogram.js can be substituted by one of several tests
testprogramAddress=0x0000;
// we want to auto-clear the console if any output is sent by the program
var consoleboxStream="";
// demonstrate write hook
writeTriggers[0x8000]="consoleboxStream += String.fromCharCode(d);"+
"consolebox.innerHTML = consoleboxStream;";
// demonstrate read hook (not used by this test program)
readTriggers[0x8004]="((consolegetc==undefined)?0:0xff)"; // return zero until we have a char
readTriggers[0x8000]="var c=consolegetc; consolegetc=undefined; (c)";
// for opcodes, see http://www.textfiles.com/programming/CARDS/6800
testprogram = [
0x21, 0x34, 0x12, // LD HL,$1234
0x31, 0xfe, 0xdc, // LD SP,0xDCFE
0xe5, // PUSH HL
0x21, 0x78, 0x56, // LD HL,$5678
0xe3, // EX (SP),HL
0xdd, 0x21, 0xbc,0x9a, // LD IX, 0x9ABC
0xdd, 0xe3, // EX (SP),IX
0x76 // HALT
]

6816
chip-z80/transdefs.js Executable file

File diff suppressed because it is too large Load Diff

151
expert-z80.html Normal file
View File

@ -0,0 +1,151 @@
<!DOCTYPE html>
<head>
<title>Visual Z80 in JavaScript</title>
<style type="text/css">@import "expert.css";</style>
<script src="chip-z80/segdefs.js"></script>
<script src="chip-z80/transdefs.js"></script>
<script src="chip-z80/nodenames.js"></script>
<script src="wires.js"></script>
<script src="expertWires.js"></script>
<script src="chipsim.js"></script>
<script src="memtable.js"></script>
<script src="macros.js"></script>
<script src="chip-z80/support.js"></script>
<script src="chip-z80/testprogram.js"></script>
<script src="3rdparty/jquery-1.3.2.min.js"></script>
<script src="3rdparty/jquery.cookie.js"></script>
<script src="3rdparty/splitter.js"></script>
<script type="text/javascript">
function handleOnload() {
/MSIE (\d+\.\d+);/.test(navigator.appVersion);
IEVersion=Number(RegExp.$1);
if((navigator.appName == 'Microsoft Internet Explorer') && (IEVersion<9)){
document.getElementById('browsertrouble').innerHTML=
'<p>Sorry, '+navigator.appName+' not supported - showing you a picture instead!</p>';
document.getElementById('frame').innerHTML='<a href="browsertrouble.html"><img src="images/jssim2.png" style="border:10px"></a>';
}else{
setTimeout(setup,200);
}
};
// initialise splitter (built on jquery)
$().ready(function(){
$("#frame").splitter({
type: "v",
outline: true,
minLeft: 20,
sizeLeft: 810,
resizeToWidth: true,
anchorToWindow: true,
});
$("#rightcolumn").splitter({
type: "h",
outline: true,
sizeBottom: 180,
minTop: 100,
});
});
</script>
</head>
<body onload="handleOnload();">
<span id="plain">
<a href="http://www.visual6502.org/faq.html">FAQ</a>&nbsp;
<a href="http://blog.visual6502.org">Blog</a>&nbsp;
<a href="http://www.visual6502.org/links.html">Links</a>&nbsp;
<a href="http://github.com/trebonian/visual6502">Source</a>&nbsp;
</span>
<div class="frame" id="frame">
<div class="leftcolumn" id="leftcolumn">
<div id="chipsurround" tabindex="1">
<div class="chip" id="chip">
<span id="waiting">Please wait, graphics initialising...</span>
<canvas class="chip" id="chipbg"></canvas>
<canvas class="chip" id="overlay"></canvas>
<canvas class="chip" id="hilite"></canvas>
<canvas class="chip" id="hitbuffer"></canvas>
</div>
</div> <!-- chipsurround -->
<div class="nochip" id="nochip">
<form>
<input type="button" value="Show chip layout" onclick="updateChipLayoutVisibility(true)" />
</form>
</div>
<div id="layoutControlPanel">
Use 'z' or '>' to zoom in, 'x' or '<' to zoom out, click to probe signals and drag to pan.
<form id="updateShow"> Show:
<input type="checkbox" name="1" id="updateShow1" onchange="updateShow(this.name,this.checked)" />(diffusion)
<input type="checkbox" name="3" id="updateShow3" onchange="updateShow(this.name,this.checked)" />(grounded diffusion)
<input type="checkbox" name="4" id="updateShow4" onchange="updateShow(this.name,this.checked)" />(powered diffusion)
<input type="checkbox" name="5" id="updateShow5" onchange="updateShow(this.name,this.checked)" />(polysilicon)
<input type="checkbox" name="0" id="updateShow0" onchange="updateShow(this.name,this.checked)" />(metal)
<input type="checkbox" name="2" id="updateShow2" onchange="updateShow(this.name,this.checked)" />(protection)
</form>
<form action="javascript:hiliteNodeList();">
<input type="button" value="Find:" onclick="hiliteNodeList();" />
<input type="text" id="HighlightThese" name="HighlightThese" value="" />
<input type="button" value="Clear Highlighting" onclick="clearHighlight();" />
<span class="animatebox">
Animate during simulation:
<input type="checkbox" id="animateModeCheckbox" onchange="updateChipLayoutAnimation(this.checked)"
/></span>
</form>
<form>
<input type="button" value="Hide Chip Layout" onclick="updateChipLayoutVisibility(false)" />
<a href="" id="linkHere" >Link to this location</a>
</form>
</div>
</div> <!-- closing leftcolumn -->
<div class="rightcolumn" id="rightcolumn">
<div id="righttopdiv">
<div class = "buttons">
<div class="twobuttons">
<a href ="javascript:stopChip()" id="stop"><img class="navstop" src="images/stop.png" title="stop"></a>
<a href ="javascript:runChip()" id="start"><img class="navplay" src="images/play.png" title="run"></a>
</div>
<div class="morebuttons">
<a href ="javascript:resetChip()"><img class="navbutton" src="images/up.png" title="reset"></a>
<a href ="javascript:stepBack()"><img class="navbutton" src="images/prev.png" title="back"></a>
<a href ="javascript:stepForward()"><img class="navbutton" src="images/next.png" title="forward"></a>
<a href ="javascript:goUntilSyncOrWrite()"><img class="navbutton" src="images/singlestep.png" title="step"></a>
<a href ="javascript:goFor()"><img class="navbutton" src="images/fastforward.png" title="fastforward"></a>
</div>
<div style="float:right;">
<a href="http://visual6502.org/wiki/index.php?title=JssimUserHelp" target="_blank">User Guide</a>
&nbsp;
</div>
</div> <!-- buttons -->
<div class="status" id="status"><p>x: 0<br>y: 0</p>
</div> <!-- status -->
<div id="memtablediv">
<table class="memtable" id="memtable" tabindex="2"></table>
</div>
</div> <!-- righttopdiv -->
<div id="tracingdiv">
<textarea id="consolebox">
click here and type if your program handles input
</textarea>
<div id="expertControlPanel" tabindex="3">
<form action="javascript:updateLogList()">
<input type="button" value="Trace more" onclick="updateLoglevel(++loglevel)" />
<input type="button" value="Trace less" onclick="updateLoglevel(--loglevel)" />
<input type="button" value="Trace these too:" onclick="updateLogList()" />
<input type="text" id="LogThese" name="LogThese" value="" />
<input type="button" value="Log Up/Down" onclick="updateLogDirection();" />
<input type="button" value="Clear Log" onclick="updateLoglevel(loglevel)" />
</form>
<br />
</div>
<div id="logstreamscroller">
<table class="logstream" id="logstream"></table>
</div>
</div>
</div> <!-- closing rightcolumn -->
</div> <!-- closing 'frame' div -->
</body>
</html>