Compare commits

..

2 Commits
master ... V0.3

Author SHA1 Message Date
Barry Silverman
416cd57947 Backport various fixes from expert 2010-10-04 15:30:25 -04:00
Barry Silverman
e5bd2a5296 Removed save.php 2010-10-04 10:43:04 -04:00
38 changed files with 4069 additions and 61921 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 834 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 855 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 830 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 840 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 843 B

File diff suppressed because one or more lines are too long

View File

@ -1,92 +0,0 @@
/**
* Cookie plugin
*
* Copyright (c) 2006 Klaus Hartl (stilbuero.de)
* Dual licensed under the MIT and GPL licenses:
* http://www.opensource.org/licenses/mit-license.php
* http://www.gnu.org/licenses/gpl.html
*
*/
/**
* Create a cookie with the given name and value and other optional parameters.
*
* @example $.cookie('the_cookie', 'the_value');
* @desc Set the value of a cookie.
* @example $.cookie('the_cookie', 'the_value', {expires: 7, path: '/', domain: 'jquery.com', secure: true});
* @desc Create a cookie with all available options.
* @example $.cookie('the_cookie', 'the_value');
* @desc Create a session cookie.
* @example $.cookie('the_cookie', null);
* @desc Delete a cookie by passing null as value.
*
* @param String name The name of the cookie.
* @param String value The value of the cookie.
* @param Object options An object literal containing key/value pairs to provide optional cookie attributes.
* @option Number|Date expires Either an integer specifying the expiration date from now on in days or a Date object.
* If a negative value is specified (e.g. a date in the past), the cookie will be deleted.
* If set to null or omitted, the cookie will be a session cookie and will not be retained
* when the the browser exits.
* @option String path The value of the path atribute of the cookie (default: path of page that created the cookie).
* @option String domain The value of the domain attribute of the cookie (default: domain of page that created the cookie).
* @option Boolean secure If true, the secure attribute of the cookie will be set and the cookie transmission will
* require a secure protocol (like HTTPS).
* @type undefined
*
* @name $.cookie
* @cat Plugins/Cookie
* @author Klaus Hartl/klaus.hartl@stilbuero.de
*/
/**
* Get the value of a cookie with the given name.
*
* @example $.cookie('the_cookie');
* @desc Get the value of a cookie.
*
* @param String name The name of the cookie.
* @return The value of the cookie.
* @type String
*
* @name $.cookie
* @cat Plugins/Cookie
* @author Klaus Hartl/klaus.hartl@stilbuero.de
*/
jQuery.cookie = function(name, value, options) {
if (typeof value != 'undefined') { // name and value given, set cookie
options = options || {};
if (value === null) {
value = '';
options.expires = -1;
}
var expires = '';
if (options.expires && (typeof options.expires == 'number' || options.expires.toUTCString)) {
var date;
if (typeof options.expires == 'number') {
date = new Date();
date.setTime(date.getTime() + (options.expires * 24 * 60 * 60 * 1000));
} else {
date = options.expires;
}
expires = '; expires=' + date.toUTCString(); // use expires attribute, max-age is not supported by IE
}
var path = options.path ? '; path=' + options.path : '';
var domain = options.domain ? '; domain=' + options.domain : '';
var secure = options.secure ? '; secure' : '';
document.cookie = [name, '=', encodeURIComponent(value), expires, path, domain, secure].join('');
} else { // only name given, get cookie
var cookieValue = null;
if (document.cookie && document.cookie != '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) == (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
};

213
3rdparty/splitter.js vendored
View File

@ -1,213 +0,0 @@
/*
* jQuery.splitter.js - two-pane splitter window plugin
*
* version 1.51 (2009/01/09)
*
* Dual licensed under the MIT and GPL licenses:
* http://www.opensource.org/licenses/mit-license.php
* http://www.gnu.org/licenses/gpl.html
*/
/**
* The splitter() plugin implements a two-pane resizable splitter window.
* The selected elements in the jQuery object are converted to a splitter;
* each selected element should have two child elements, used for the panes
* of the splitter. The plugin adds a third child element for the splitbar.
*
* For more details see: http://methvin.com/splitter/
*
*
* @example $('#MySplitter').splitter();
* @desc Create a vertical splitter with default settings
*
* @example $('#MySplitter').splitter({type: 'h', accessKey: 'M'});
* @desc Create a horizontal splitter resizable via Alt+Shift+M
*
* @name splitter
* @type jQuery
* @param Object options Options for the splitter (not required)
* @cat Plugins/Splitter
* @return jQuery
* @author Dave Methvin (dave.methvin@gmail.com)
*/
;(function($){
$.fn.splitter = function(args){
args = args || {};
return this.each(function() {
var zombie; // left-behind splitbar for outline resizes
function startSplitMouse(evt) {
if ( opts.outline )
zombie = zombie || bar.clone(false).insertAfter(A);
panes.css("-webkit-user-select", "none"); // Safari selects A/B text on a move
bar.addClass(opts.activeClass);
A._posSplit = A[0][opts.pxSplit] - evt[opts.eventPos];
$(document)
.bind("mousemove", doSplitMouse)
.bind("mouseup", endSplitMouse);
}
function doSplitMouse(evt) {
var newPos = A._posSplit+evt[opts.eventPos];
if ( opts.outline ) {
newPos = Math.max(0, Math.min(newPos, splitter._DA - bar._DA));
bar.css(opts.origin, newPos);
} else
resplit(newPos);
}
function endSplitMouse(evt) {
bar.removeClass(opts.activeClass);
var newPos = A._posSplit+evt[opts.eventPos];
if ( opts.outline ) {
zombie.remove(); zombie = null;
resplit(newPos);
}
panes.css("-webkit-user-select", "text"); // let Safari select text again
$(document)
.unbind("mousemove", doSplitMouse)
.unbind("mouseup", endSplitMouse);
}
function resplit(newPos) {
// Constrain new splitbar position to fit pane size limits
newPos = Math.max(A._min, splitter._DA - B._max,
Math.min(newPos, A._max, splitter._DA - bar._DA - B._min));
// Resize/position the two panes
bar._DA = bar[0][opts.pxSplit]; // bar size may change during dock
bar.css(opts.origin, newPos).css(opts.fixed, splitter._DF);
A.css(opts.origin, 0).css(opts.split, newPos).css(opts.fixed, splitter._DF);
B.css(opts.origin, newPos+bar._DA)
.css(opts.split, splitter._DA-bar._DA-newPos).css(opts.fixed, splitter._DF);
// IE fires resize for us; all others pay cash
if ( !$.browser.msie )
panes.trigger("resize");
}
function dimSum(jq, dims) {
// Opera returns -1 for missing min/max width, turn into 0
var sum = 0;
for ( var i=1; i < arguments.length; i++ )
sum += Math.max(parseInt(jq.css(arguments[i])) || 0, 0);
return sum;
}
// Determine settings based on incoming opts, element classes, and defaults
var vh = (args.splitHorizontal? 'h' : args.splitVertical? 'v' : args.type) || 'v';
var opts = $.extend({
activeClass: 'active', // class name for active splitter
pxPerKey: 8, // splitter px moved per keypress
tabIndex: 0, // tab order indicator
accessKey: '' // accessKey for splitbar
},{
v: { // Vertical splitters:
keyLeft: 39, keyRight: 37, cursor: "e-resize",
splitbarClass: "vsplitbar", outlineClass: "voutline",
type: 'v', eventPos: "pageX", origin: "left",
split: "width", pxSplit: "offsetWidth", side1: "Left", side2: "Right",
fixed: "height", pxFixed: "offsetHeight", side3: "Top", side4: "Bottom"
},
h: { // Horizontal splitters:
keyTop: 40, keyBottom: 38, cursor: "n-resize",
splitbarClass: "hsplitbar", outlineClass: "houtline",
type: 'h', eventPos: "pageY", origin: "top",
split: "height", pxSplit: "offsetHeight", side1: "Top", side2: "Bottom",
fixed: "width", pxFixed: "offsetWidth", side3: "Left", side4: "Right"
}
}[vh], args);
// Create jQuery object closures for splitter and both panes
var splitter = $(this).css({position: "relative"});
var panes = $(">*", splitter[0]).css({
position: "absolute", // positioned inside splitter container
"z-index": "1", // splitbar is positioned above
"-moz-outline-style": "none" // don't show dotted outline
});
var A = $(panes[0]); // left or top
var B = $(panes[1]); // right or bottom
// Focuser element, provides keyboard support; title is shown by Opera accessKeys
var focuser = $('<a href="javascript:void(0)"></a>')
.attr({accessKey: opts.accessKey, tabIndex: opts.tabIndex, title: opts.splitbarClass})
.bind($.browser.opera?"click":"focus", function(){ this.focus(); bar.addClass(opts.activeClass) })
.bind("keydown", function(e){
var key = e.which || e.keyCode;
var dir = key==opts["key"+opts.side1]? 1 : key==opts["key"+opts.side2]? -1 : 0;
if ( dir )
resplit(A[0][opts.pxSplit]+dir*opts.pxPerKey, false);
})
.bind("blur", function(){ bar.removeClass(opts.activeClass) });
// Splitbar element, can be already in the doc or we create one
var bar = $(panes[2] || '<div></div>')
.insertAfter(A).css("z-index", "100").append(focuser)
.attr({"class": opts.splitbarClass, unselectable: "on"})
.css({position: "absolute", "user-select": "none", "-webkit-user-select": "none",
"-khtml-user-select": "none", "-moz-user-select": "none"})
.bind("mousedown", startSplitMouse);
// Use our cursor unless the style specifies a non-default cursor
if ( /^(auto|default|)$/.test(bar.css("cursor")) )
bar.css("cursor", opts.cursor);
// Cache several dimensions for speed, rather than re-querying constantly
bar._DA = bar[0][opts.pxSplit];
splitter._PBF = $.boxModel? dimSum(splitter, "border"+opts.side3+"Width", "border"+opts.side4+"Width") : 0;
splitter._PBA = $.boxModel? dimSum(splitter, "border"+opts.side1+"Width", "border"+opts.side2+"Width") : 0;
A._pane = opts.side1;
B._pane = opts.side2;
$.each([A,B], function(){
this._min = opts["min"+this._pane] || dimSum(this, "min-"+opts.split);
this._max = opts["max"+this._pane] || dimSum(this, "max-"+opts.split) || 9999;
this._init = opts["size"+this._pane]===true ?
parseInt($.curCSS(this[0],opts.split)) : opts["size"+this._pane];
});
// Determine initial position, get from cookie if specified
var initPos = A._init;
if ( !isNaN(B._init) ) // recalc initial B size as an offset from the top or left side
initPos = splitter[0][opts.pxSplit] - splitter._PBA - B._init - bar._DA;
if ( opts.cookie ) {
if ( !$.cookie )
alert('jQuery.splitter(): jQuery cookie plugin required');
var ckpos = parseInt($.cookie(opts.cookie));
if ( !isNaN(ckpos) )
initPos = ckpos;
$(window).bind("unload", function(){
var state = String(bar.css(opts.origin)); // current location of splitbar
$.cookie(opts.cookie, state, {expires: opts.cookieExpires || 365,
path: opts.cookiePath || document.location.pathname});
});
}
if ( isNaN(initPos) ) // King Solomon's algorithm
initPos = Math.round((splitter[0][opts.pxSplit] - splitter._PBA - bar._DA)/2);
// Resize event propagation and splitter sizing
if ( opts.anchorToWindow ) {
// Account for margin or border on the splitter container and enforce min height
splitter._hadjust = dimSum(splitter, "borderTopWidth", "borderBottomWidth", "marginBottom");
splitter._hmin = Math.max(dimSum(splitter, "minHeight"), 20);
$(window).bind("resize", function(){
var top = splitter.offset().top;
var wh = $(window).height();
splitter.css("height", Math.max(wh-top-splitter._hadjust, splitter._hmin)+"px");
if ( !$.browser.msie ) splitter.trigger("resize");
}).trigger("resize");
}
else if ( opts.resizeToWidth && !$.browser.msie )
$(window).bind("resize", function(){
splitter.trigger("resize");
});
// Resize event handler; triggered immediately to set initial position
splitter.bind("resize", function(e, size){
// Custom events bubble in jQuery 1.3; don't Yo Dawg
if ( e.target != this ) return;
// Determine new width/height of splitter container
splitter._DF = splitter[0][opts.pxFixed] - splitter._PBF;
splitter._DA = splitter[0][opts.pxSplit] - splitter._PBA;
// Bail if splitter isn't visible or content isn't there yet
if ( splitter._DF <= 0 || splitter._DA <= 0 ) return;
// Re-divvy the adjustable dimension; maintain size of the preferred pane
resplit(!isNaN(size)? size : (!(opts.sizeRight||opts.sizeBottom)? A[0][opts.pxSplit] :
splitter._DA-B[0][opts.pxSplit]-bar._DA));
}).trigger("resize" , [initPos]);
});
};
})(jQuery);

4
README
View File

@ -1,11 +1,9 @@
This is the JavaScript simulator from the visual6502.org project:
This is the javascript simulator from the visual5602.org project:
www.visual6502.org/JSSim
It includes a general purpose transistor-level simulator, layout browser,
and the data from a 6502 revD chip.
It also includes a similar simulator for the 6800 chip.
Note the various licenses and Copyright associated with each file.
Enjoy!

View File

@ -2,7 +2,7 @@
<head>
<title>Visual 6502 in JavaScript</title>
<style type="text/css">@import "kiosk.css";</style>
<style type="text/css">@import "wires.css";</style>
</head>
<body>

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -1,488 +0,0 @@
// chip-specific support functions
//
// may override function definitions made previously
chipname='6800';
grChipSize=6600;
grChipOffsetX=25
grChipOffsetY=-200;
ngnd = nodenames['gnd'];
npwr = nodenames['vcc'];
nodenamereset = 'reset';
presetLogLists=[
['cycle',],
['ab','db','rw','vma','Fetch','pc','acca','accb','ix','sp','p'],
['ir','sync','Execute','State'], // instruction fetch and execution control
['dbi','dbo','tmp','sum','inc'], // internal register-sized state
['idb','abh','abl','ablx'], // internal datapath busses
['irq','nmi',nodenamereset,'tsc','dbe','halt','ba'], // other pins
];
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['phi2']);
eval(clockTriggers[cycle]);
if (clk) {setLow('phi2'); setLow('dbe'); setHigh('phi1'); handleBusRead(); }
else {setHigh('phi1'); setLow('phi1'); setHigh('phi2'); setHigh('dbe'); handleBusWrite();}
}
function goUntilSyncOrWrite(){
halfStep();
cycle++;
while(
!isNodeHigh(nodenames['phi2']) ||
( !isNodeHigh(nodenames['sync']) && isNodeHigh(nodenames['rw']) )
) {
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);
setHigh('phi1'); setLow('phi2'); setLow('dbe');
setHigh('dbe'); setLow('tsc'); setHigh('halt');
setHigh('irq'); setHigh('nmi');
recalcNodeList(allNodes());
for(var i=0;i<8;i++){
setLow('phi1');
setHigh('phi2'); setHigh('dbe');
setLow('phi2'); setLow('dbe');
setHigh('phi1');
}
setHigh(nodenamereset);
for(var i=0;i<6;i++){halfStep();} // avoid updating graphics and trace buffer before user code
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['rw'])){
var a = readAddressBus();
var d = eval(readTriggers[a]);
if(d == undefined)
d = mRead(readAddressBus());
if(isNodeHigh(nodenames['sync']))
eval(fetchTriggers[d]);
writeDataBus(d);
}
}
function readAccA(){return readBits('acca', 8);}
function readAccB(){return readBits('accb', 8);}
function readIX(){return (readBits('ixh', 8)<<8) + readBits('ixl', 8);}
function readSP(){return (readBits('sph', 8)<<8) + readBits('spl', 8);}
function readPstring(){
var result;
result = '&#8209' + // non-breaking hyphen
'&#8209' + // non-breaking hyphen
(isNodeHigh(nodenames['flagh'])?'H':'h') +
(isNodeHigh(nodenames['flagi'])?'I':'i') +
(isNodeHigh(nodenames['flagn'])?'N':'n') +
(isNodeHigh(nodenames['flagz'])?'Z':'z') +
(isNodeHigh(nodenames['flagv'])?'V':'v') +
(isNodeHigh(nodenames['flagc'])?'C':'c');
return result;
}
// The 6800 state control is something like a branching shift register
// ... but not quite like that
TCStates=[
"Ts", "Tf",
"Tx0", "Tx1", "Tx2",
"Ta0", "Ta1", "Ta2",
"Td0_0",
"#Te0", "Te1_0",
"Tg0", "Tg1", "Tg2", "Tg3", "Tg4", "Tg5", "Tg6", "Tg7", "Tg8",
"Tr3", "Tr4", "Tr5", "Tr6", "Tr7", "Tr8",
];
function listActiveTCStates() {
var s=[];
for(var i=0;i<TCStates.length;i++){
var t=TCStates[i];
// remove a leading hash, but invert the signal
// in any case, remove any trailing suffix
if(t[0]=="#"){
if(!isNodeHigh(nodenames[t])) s.push(t.slice(1,4));
} else {
if(isNodeHigh(nodenames[t])) s.push(t.slice(0,3));
}
}
return s.join("+");
}
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=='pc')
return busToHex('pch') + busToHex('pcl');
if(busname=='sp')
return busToHex('sph') + busToHex('spl');
if(busname=='ix')
return busToHex('ixh') + busToHex('ixl');
if(busname=='inc')
return busToHex('inch') + busToHex('incl');
if(busname=='p')
return readPstring();
if(busname=='State')
return listActiveTCStates();
if(busname=='Execute')
return disassemblytoHTML(readBits('ir',8));
if(busname=='Fetch')
return isNodeHigh(nodenames['sync'])?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 +
' phi0:' + readBit('phi2') +
' AB:' + hexWord(ab) +
' D:' + hexByte(readDataBus()) +
' RnW:' + readBit('rw') +
' VMA:' + readBit('vma');
var machine2 =
' PC:' + hexWord(readPC()) +
' A:' + hexByte(readAccA()) +
' B:' + hexByte(readAccB()) +
' IX:' + hexWord(readIX()) +
' SP:' + hexWord(readSP()) +
' ' + readPstring();
var machine3 =
'Hz: ' + estimatedHz().toFixed(1);
if(typeof expertMode != "undefined") {
machine3 += ' Exec: ' + busToString('Execute'); // no T-state info for 6800 yet
if(isNodeHigh(nodenames['sync']))
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);
}
// javascript derived from http://segher.ircgeeks.net/6800/OPS
var disassembly={
0x00: "!",
0x01: "nop",
0x02: "!",
0x03: "!",
0x04: "!",
0x05: "!",
0x06: "tap",
0x07: "tpa",
0x10: "sba",
0x11: "cba",
0x12: "!",
0x13: "!",
0x14: "!nba",
0x15: "!",
0x16: "tab",
0x17: "tba",
0x20: "bra N",
0x21: "!",
0x22: "bhi N",
0x23: "bls N",
0x24: "bcc N",
0x25: "bcs N",
0x26: "bne N",
0x27: "beq N",
0x30: "tsx",
0x31: "ins",
0x32: "pul a",
0x33: "pul b",
0x34: "des",
0x35: "txs",
0x36: "psh a",
0x37: "psh b",
0x40: "neg a",
0x41: "!",
0x42: "!",
0x43: "com a",
0x44: "lsr a",
0x45: "!",
0x46: "ror a",
0x47: "asr a",
0x50: "neg b",
0x51: "!",
0x52: "!",
0x53: "com b",
0x54: "lsr b",
0x55: "!",
0x56: "ror b",
0x57: "asr b",
0x60: "neg Nx",
0x61: "!",
0x62: "!",
0x63: "com Nx",
0x64: "lsr Nx",
0x65: "!",
0x66: "ror Nx",
0x67: "asr Nx",
0x70: "neg NN",
0x71: "!",
0x72: "!",
0x73: "com NN",
0x74: "lsr NN",
0x75: "!",
0x76: "ror NN",
0x77: "asr NN",
0x80: "sub a #",
0x81: "cmp a #",
0x82: "sbc a #",
0x83: "!",
0x84: "and a #",
0x85: "bit a #",
0x86: "lda a #",
0x87: "!",
0x90: "sub a N",
0x91: "cmp a N",
0x92: "sbc a N",
0x93: "!",
0x94: "and a N",
0x95: "bit a N",
0x96: "lda a N",
0x97: "sta a N",
0xa0: "sub a Nx",
0xa1: "cmp a Nx",
0xa2: "sbc a Nx",
0xa3: "!",
0xa4: "and a Nx",
0xa5: "bit a Nx",
0xa6: "lda a Nx",
0xa7: "sta a Nx",
0xb0: "sub a NN",
0xb1: "cmp a NN",
0xb2: "sbc a NN",
0xb3: "!",
0xb4: "and a NN",
0xb5: "bit a NN",
0xb6: "lda a NN",
0xb7: "sta a NN",
0xc0: "sub b #",
0xc1: "cmp b #",
0xc2: "sbc b #",
0xc3: "!",
0xc4: "and b #",
0xc5: "bit b #",
0xc6: "lda b #",
0xc7: "!",
0xd0: "sub b N",
0xd1: "cmp b N",
0xd2: "sbc b N",
0xd3: "!",
0xd4: "and b N",
0xd5: "bit b N",
0xd6: "lda b N",
0xd7: "sta b N",
0xe0: "sub b Nx",
0xe1: "cmp b Nx",
0xe2: "sbc b Nx",
0xe3: "!",
0xe4: "and b Nx",
0xe5: "bit b Nx",
0xe6: "lda b Nx",
0xe7: "sta b Nx",
0xf0: "sub b NN",
0xf1: "cmp b NN",
0xf2: "sbc b NN",
0xf3: "!",
0xf4: "and b NN",
0xf5: "bit b NN",
0xf6: "lda b NN",
0xf7: "sta b NN",
0x08: "inx",
0x09: "dex",
0x0a: "clv",
0x0b: "sev",
0x0c: "clc",
0x0d: "sec",
0x0e: "cli",
0x0f: "sei",
0x18: "!",
0x19: "daa",
0x1a: "!",
0x1b: "aba",
0x1c: "!",
0x1d: "!",
0x1e: "!",
0x1f: "!",
0x28: "bvc N",
0x29: "bvs N",
0x2a: "bpl N",
0x2b: "bmi N",
0x2c: "bge N",
0x2d: "blt N",
0x2e: "bgt N",
0x2f: "ble N",
0x38: "!",
0x39: "rts",
0x3a: "!",
0x3b: "rti",
0x3c: "!",
0x3d: "!",
0x3e: "wai",
0x3f: "swi",
0x48: "asl a",
0x49: "rol a",
0x4a: "dec a",
0x4b: "!",
0x4c: "inc a",
0x4d: "tst a",
0x4e: "!",
0x4f: "clr a",
0x58: "asl b",
0x59: "rol b",
0x5a: "dec b",
0x5b: "!",
0x5c: "inc b",
0x5d: "tst b",
0x5e: "!",
0x5f: "clr b",
0x68: "asl Nx",
0x69: "rol Nx",
0x6a: "dec Nx",
0x6b: "!",
0x6c: "inc Nx",
0x6d: "tst Nx",
0x6e: "jmp Nx",
0x6f: "clr Nx",
0x78: "asl NN",
0x79: "rol NN",
0x7a: "dec NN",
0x7b: "!",
0x7c: "inc NN",
0x7d: "tst NN",
0x7e: "jmp NN",
0x7f: "clr NN",
0x88: "eor a #",
0x89: "adc a #",
0x8a: "ora a #",
0x8b: "add a #",
0x8c: "cpx ##",
0x8d: "bsr N",
0x8e: "lds ##",
0x8f: "!",
0x98: "eor a N",
0x99: "adc a N",
0x9a: "ora a N",
0x9b: "add a N",
0x9c: "cpx N",
0x9d: "!hcf",
0x9e: "lds N",
0x9f: "sts N",
0xa8: "eor a Nx",
0xa9: "adc a Nx",
0xaa: "ora a Nx",
0xab: "add a Nx",
0xac: "cpx Nx",
0xad: "jsr Nx",
0xae: "lds Nx",
0xaf: "sts Nx",
0xb8: "eor a NN",
0xb9: "adc a NN",
0xba: "ora a NN",
0xbb: "add a NN",
0xbc: "cpx NN",
0xbd: "jsr NN",
0xbe: "lds NN",
0xbf: "sts NN",
0xc8: "eor b #",
0xc9: "adc b #",
0xca: "ora b #",
0xcb: "add b #",
0xcc: "!",
0xcd: "!",
0xce: "ldx ##",
0xcf: "!",
0xd8: "eor b N",
0xd9: "adc b N",
0xda: "ora b N",
0xdb: "add b N",
0xdc: "!",
0xdd: "!hcf",
0xde: "ldx N",
0xdf: "stx N",
0xe8: "eor b Nx",
0xe9: "adc b Nx",
0xea: "ora b Nx",
0xeb: "add b Nx",
0xec: "!",
0xed: "!",
0xee: "ldx Nx",
0xef: "stx Nx",
0xf8: "eor b NN",
0xf9: "adc b NN",
0xfa: "ora b NN",
0xfb: "add b NN",
0xfc: "!",
0xfd: "!",
0xfe: "ldx NN",
0xff: "stx NN",
};

View File

@ -1,31 +0,0 @@
// 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 = [
0xce, 0x43, 0x21, // LDX #4321
0x35, // TXS
0xce, 0x80, 0x00, // LDX #8000
0xc6, 0x40, // LDAB #$40
0xbd, 0x00, 0x10, // JSR $0010
0x7e, 0x00, 0x09, // JMP $0009
0x01, // NOP
0x4a, // DECA
0xe7, 0x00, // STAB 0, X
0x7c, 0x00, 0x0f, // INC $0F
0x0d, // SEC
0xc9, 0x02, // ADCB #$02
0x39, // RTS
]

File diff suppressed because it is too large Load Diff

View File

@ -1,530 +0,0 @@
// ***********************************************************
// * This file is automatically generated by Z80Simulator. *
// * Please do not manually edit! Instead, find a transistor *
// * that uses the new signal and use FindTransistor(x,y) in *
// * Z80Simulator to cause that signal to be added. *
// * This seems a pain, but it has two advantages: *
// * - all signals are then available in Z80Simulator *
// * - it avoids renumbering issues if/when the PNGs change *
// ***********************************************************
var nodenames ={
// Pads
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,
wait: 22,
_int: 23,
int: 23,
_irq: 23,
irq: 23,
_nmi: 24,
nmi: 24,
_busrq: 25,
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,
// T-States
t1: 115,
t2: 137,
t3: 144,
t4: 166,
t5: 134,
t6: 168,
// Machine cycles
m1: 155,
m2: 173,
m3: 163,
m4: 159,
m5: 209,
m6: 210,
// EXX latches
ex_af: 631,
ex_bcdehl: 1770,
ex_dehl0: 625,
ex_dehl1: 629,
ex_dehl_combined: 626,
// Registers
reg_a0: 2245,
reg_a1: 2319,
reg_a2: 2357,
reg_a3: 2442,
reg_a4: 2463,
reg_a5: 2552,
reg_a6: 2586,
reg_a7: 2656,
reg_f0: 1827,
reg_f1: 1903,
reg_f2: 1928,
reg_f3: 2009,
reg_f4: 2032,
reg_f5: 2107,
reg_f6: 2132,
reg_f7: 2209,
reg_b0: 2242,
reg_b1: 2316,
reg_b2: 2354,
reg_b3: 2439,
reg_b4: 2460,
reg_b5: 2549,
reg_b6: 2583,
reg_b7: 2653,
reg_c0: 1824,
reg_c1: 1900,
reg_c2: 1925,
reg_c3: 2006,
reg_c4: 2029,
reg_c5: 2104,
reg_c6: 2129,
reg_c7: 2206,
reg_d0: 2238,
reg_d1: 2312,
reg_d2: 2350,
reg_d3: 2435,
reg_d4: 2456,
reg_d5: 2545,
reg_d6: 2579,
reg_d7: 2649,
reg_e0: 1820,
reg_e1: 1896,
reg_e2: 1921,
reg_e3: 2002,
reg_e4: 2025,
reg_e5: 2100,
reg_e6: 2125,
reg_e7: 2202,
reg_h0: 2240,
reg_h1: 2314,
reg_h2: 2352,
reg_h3: 2437,
reg_h4: 2458,
reg_h5: 2547,
reg_h6: 2581,
reg_h7: 2651,
reg_l0: 1822,
reg_l1: 1898,
reg_l2: 1923,
reg_l3: 2004,
reg_l4: 2027,
reg_l5: 2102,
reg_l6: 2127,
reg_l7: 2204,
reg_w0: 2234,
reg_w1: 2308,
reg_w2: 2346,
reg_w3: 2431,
reg_w4: 2452,
reg_w5: 2541,
reg_w6: 2575,
reg_w7: 2645,
reg_z0: 1816,
reg_z1: 1892,
reg_z2: 1917,
reg_z3: 1998,
reg_z4: 2021,
reg_z5: 2096,
reg_z6: 2121,
reg_z7: 2198,
reg_pch0: 2232,
reg_pch1: 2306,
reg_pch2: 2344,
reg_pch3: 2429,
reg_pch4: 2450,
reg_pch5: 2539,
reg_pch6: 2573,
reg_pch7: 2643,
reg_pcl0: 1814,
reg_pcl1: 1890,
reg_pcl2: 1915,
reg_pcl3: 1996,
reg_pcl4: 2019,
reg_pcl5: 2094,
reg_pcl6: 2119,
reg_pcl7: 2196,
reg_sph0: 2235,
reg_sph1: 2309,
reg_sph2: 2347,
reg_sph3: 2432,
reg_sph4: 2453,
reg_sph5: 2542,
reg_sph6: 2576,
reg_sph7: 2646,
reg_spl0: 1817,
reg_spl1: 1893,
reg_spl2: 1918,
reg_spl3: 1999,
reg_spl4: 2022,
reg_spl5: 2097,
reg_spl6: 2122,
reg_spl7: 2199,
reg_ixh0: 2237,
reg_ixh1: 2311,
reg_ixh2: 2349,
reg_ixh3: 2434,
reg_ixh4: 2455,
reg_ixh5: 2544,
reg_ixh6: 2578,
reg_ixh7: 2648,
reg_ixl0: 1819,
reg_ixl1: 1895,
reg_ixl2: 1920,
reg_ixl3: 2001,
reg_ixl4: 2024,
reg_ixl5: 2099,
reg_ixl6: 2124,
reg_ixl7: 2201,
reg_iyh0: 2236,
reg_iyh1: 2310,
reg_iyh2: 2348,
reg_iyh3: 2433,
reg_iyh4: 2454,
reg_iyh5: 2543,
reg_iyh6: 2577,
reg_iyh7: 2647,
reg_iyl0: 1818,
reg_iyl1: 1894,
reg_iyl2: 1919,
reg_iyl3: 2000,
reg_iyl4: 2023,
reg_iyl5: 2098,
reg_iyl6: 2123,
reg_iyl7: 2200,
reg_i0: 2233,
reg_i1: 2307,
reg_i2: 2345,
reg_i3: 2430,
reg_i4: 2451,
reg_i5: 2540,
reg_i6: 2574,
reg_i7: 2644,
reg_r0: 1815,
reg_r1: 1891,
reg_r2: 1916,
reg_r3: 1997,
reg_r4: 2020,
reg_r5: 2095,
reg_r6: 2120,
reg_r7: 2197,
reg_aa0: 2244,
reg_aa1: 2318,
reg_aa2: 2356,
reg_aa3: 2441,
reg_aa4: 2462,
reg_aa5: 2551,
reg_aa6: 2585,
reg_aa7: 2655,
reg_ff0: 1826,
reg_ff1: 1902,
reg_ff2: 1927,
reg_ff3: 2008,
reg_ff4: 2031,
reg_ff5: 2106,
reg_ff6: 2131,
reg_ff7: 2208,
reg_bb0: 2243,
reg_bb1: 2317,
reg_bb2: 2355,
reg_bb3: 2440,
reg_bb4: 2461,
reg_bb5: 2550,
reg_bb6: 2584,
reg_bb7: 2654,
reg_cc0: 1825,
reg_cc1: 1901,
reg_cc2: 1926,
reg_cc3: 2007,
reg_cc4: 2030,
reg_cc5: 2105,
reg_cc6: 2130,
reg_cc7: 2207,
reg_dd0: 2239,
reg_dd1: 2313,
reg_dd2: 2351,
reg_dd3: 2436,
reg_dd4: 2457,
reg_dd5: 2546,
reg_dd6: 2580,
reg_dd7: 2650,
reg_ee0: 1821,
reg_ee1: 1897,
reg_ee2: 1922,
reg_ee3: 2003,
reg_ee4: 2026,
reg_ee5: 2101,
reg_ee6: 2126,
reg_ee7: 2203,
reg_hh0: 2241,
reg_hh1: 2315,
reg_hh2: 2353,
reg_hh3: 2438,
reg_hh4: 2459,
reg_hh5: 2548,
reg_hh6: 2582,
reg_hh7: 2652,
reg_ll0: 1823,
reg_ll1: 1899,
reg_ll2: 1924,
reg_ll3: 2005,
reg_ll4: 2028,
reg_ll5: 2103,
reg_ll6: 2128,
reg_ll7: 2205,
// Data buses and control
dp_dl: 82,
dl_dp: 165,
load_ir: 1354,
dlatch0: 123,
dlatch1: 195,
dlatch2: 414,
dlatch3: 930,
dlatch4: 1000,
dlatch5: 872,
dlatch6: 751,
dlatch7: 358,
dl_d: 87,
d_dl: 133,
dbus0: 138,
dbus1: 196,
dbus2: 412,
dbus3: 480,
dbus4: 485,
dbus5: 486,
dbus6: 380,
dbus7: 370,
_instr0: 1350,
_instr1: 1360,
_instr2: 1366,
_instr3: 1380,
_instr4: 1388,
_instr5: 1395,
_instr6: 1370,
_instr7: 1375,
instr0: 1348,
instr1: 1359,
instr2: 1365,
instr3: 1379,
instr4: 1387,
instr5: 1394,
instr6: 1369,
instr7: 1374,
d_u: 546,
ubus0: 545,
ubus1: 528,
ubus2: 526,
ubus3: 770,
ubus4: 779,
ubus5: 790,
ubus6: 716,
ubus7: 525,
u_v: 750,
vbus0: 755,
vbus1: 772,
vbus2: 783,
vbus3: 796,
vbus4: 803,
vbus5: 808,
vbus6: 836,
vbus7: 839,
rl_wr: 678,
rh_wr: 652,
r_u: 692,
r_v: 693,
regbit0: 702,
regbit1: 732,
regbit2: 738,
regbit3: 775,
regbit4: 776,
regbit5: 807,
regbit6: 809,
regbit7: 864,
regbit8: 870,
regbit9: 902,
regbit10: 906,
regbit11: 934,
regbit12: 935,
regbit13: 970,
regbit14: 973,
regbit15: 999,
r_p: 1785,
r_x1: 608,
pcbit0: 703,
pcbit1: 731,
pcbit2: 739,
pcbit3: 774,
pcbit4: 777,
pcbit5: 806,
pcbit6: 810,
pcbit7: 863,
pcbit8: 871,
pcbit9: 901,
pcbit10: 907,
pcbit11: 933,
pcbit12: 936,
pcbit13: 969,
pcbit14: 974,
pcbit15: 998,
// ALU
alubus0: 837,
alubus1: 889,
alubus2: 937,
alubus3: 983,
alubus4: 852,
alubus5: 903,
alubus6: 951,
alubus7: 995,
alua0: 850,
alua1: 899,
alua2: 947,
alua3: 993,
alua4: 868,
alua5: 920,
alua6: 968,
alua7: 1007,
alub0: 845,
alub1: 897,
alub2: 944,
alub3: 988,
alub4: 867,
alub5: 918,
alub6: 966,
alub7: 1005,
aluout0: 2211,
aluout1: 2338,
aluout2: 2504,
aluout3: 816,
alulat0: 865,
alulat1: 912,
alulat2: 960,
alulat3: 1002,
// PLA
pla0: 287,
pla1: 332,
pla2: 314,
pla3: 333,
pla4: 315,
pla5: 334,
pla6: 316,
pla7: 335,
pla8: 317,
pla9: 336,
pla10: 318,
pla11: 361,
pla12: 261,
pla13: 337,
pla14: 319,
pla15: 464,
pla16: 288,
pla17: 338,
pla18: 320,
pla19: 364,
pla20: 325,
pla21: 324,
pla22: 308,
pla23: 289,
pla24: 339,
pla25: 313,
pla26: 340,
pla27: 290,
pla28: 341,
pla29: 291,
pla30: 342,
pla31: 292,
pla32: 365,
pla33: 293,
pla34: 362,
pla35: 294,
pla36: 331,
pla37: 293,
pla38: 343,
pla39: 296,
pla40: 297,
pla41: 298,
pla42: 344,
pla43: 299,
pla44: 269,
pla45: 300,
pla46: 237,
pla47: 301,
pla48: 345,
pla49: 302,
pla50: 346,
pla51: 264,
pla52: 266,
pla53: 347,
pla54: 303,
pla55: 356,
pla56: 227,
pla57: 366,
pla58: 304,
pla59: 305,
pla60: 271,
pla61: 348,
pla62: 306,
pla63: 309,
pla64: 311,
pla65: 312,
pla66: 307,
pla67: 367,
pla68: 272,
pla69: 349,
pla70: 273,
pla71: 350,
pla72: 274,
pla73: 351,
pla74: 275,
pla75: 276,
pla76: 268,
pla77: 352,
pla78: 277,
pla79: 278,
pla80: 279,
pla81: 280,
pla82: 368,
pla83: 281,
pla84: 282,
pla85: 283,
pla86: 284,
pla87: 285,
pla88: 286,
pla89: 321,
pla90: 353,
pla91: 322,
pla92: 354,
pla93: 323,
pla94: 369,
pla95: 258,
pla96: 249,
pla97: 245,
pla98: 355,
}

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@ -1,73 +0,0 @@
// 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 = [
0x00, // NOP
0x31, 0x00, 0x01, // LD SP,0x0100
0xCD, 0x0B, 0x00, // CALL $000B
0x00, // NOP
0x21, 0x78, 0x56, // LD HL,$5678
0x21, 0x34, 0x12, // LD HL,$1234
0xe5, // PUSH HL
0x00, // NOP
0x00, // NOP
0x3C, // INC A
0x04, // INC B
0x15, // DEC D
0x24, // INC H
0xEB, // EXX DE,HL
0x00, // NOP
0x3C, // INC A
0x04, // INC B
0x15, // DEC D
0x24, // INC H
0xD9, // EXX
0x00, // NOP
0x3C, // INC A
0x04, // INC B
0x15, // DEC D
0x24, // INC H
0xEB, // EXX DE,HL
0x00, // NOP
0x3C, // INC A
0x04, // INC B
0x15, // DEC D
0x24, // INC H
0x08, // EXX AF,AF'
0x00, // NOP
0x3C, // INC A
0x04, // INC B
0x15, // DEC D
0x24, // INC H
0x00, // NOP
0x00, // NOP
0x00, // NOP
0x21, 0x00, 0x01, // LD HL,$0100
0x36, 0xCC, // LD (HL),$CC
0x00, // NOP
0x7E, // LD A, (HL)
0x00, // NOP
// Pavel's original test program
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
0x00 // NOP
]

File diff suppressed because it is too large Load Diff

View File

@ -21,116 +21,123 @@
*/
var ctrace = false;
var traceTheseNodes = [];
var traceTheseTransistors = [];
var loglevel = 0;
var recalclist = new Array();
var recalcHash = new Array();
var group = new Array();
var noGraphics = false;
var loglevel = 3;
var ridx = 0;
function recalcNodeList(list){
var n = list[0];
recalclist = new Array();
recalcHash = new Array();
var recalclist = new Array();
for(var j=0;j<100;j++){ // loop limiter
if(list.length==0) return;
if(ctrace) {
var i;
for(i=0;i<traceTheseNodes.length;i++) {
if(list.indexOf(traceTheseNodes[i])!=-1) break;
}
if((traceTheseNodes.length==0)||(list.indexOf(traceTheseNodes[i])==-1)) {
console.log('recalcNodeList iteration: ', j, list.length, 'nodes');
} else {
console.log('recalcNodeList iteration: ', j, list.length, 'nodes', list);
}
}
list.forEach(recalcNode);
if(ctrace) console.log(j, list);
for(var i in list) recalcNode(list[i], recalclist);
list = recalclist;
recalclist = new Array();
recalcHash = new Array();
}
if(ctrace) console.log(n,'looping...');
}
function recalcNode(node){
function recalcNode(node, recalclist){
if(node==ngnd) return;
if(node==npwr) return;
getNodeGroup(node);
var newState = getNodeValue();
if(ctrace && (traceTheseNodes.indexOf(node)!=-1))
console.log('recalc', node, group);
group.forEach(function(i){
var n = nodes[i];
if(n.state==newState) return;
n.state = newState;
n.gates.forEach(function(t){
if(n.state) turnTransistorOn(t);
else turnTransistorOff(t);});
});
var group = getNodeGroup(node);
var newv = getNodeValue(group);
if(ctrace) console.log('recalc', node, group);
for(var i in group){
var n = nodes[group[i]];
if(n.state!=newv && ctrace) console.log(group[i], n.state, newv);
n.state = newv;
for(var t in n.gates) recalcTransistor(n.gates[t], recalclist);
}
}
function turnTransistorOn(t){
function recalcTransistor(tn, recalclist){
var t = transistors[tn];
if(isNodeHigh(t.gate)) turnTransistorOn(t, recalclist);
else turnTransistorOff(t, recalclist);
}
function turnTransistorOn(t, recalclist){
if(t.on) return;
if(ctrace && (traceTheseTransistors.indexOf(t.name)!=-1))
console.log(t.name, 'on', t.gate, t.c1, t.c2);
if(ctrace) console.log(t.name, 'on', t.gate, t.c1, t.c2);
t.on = true;
addRecalcNode(t.c1);
addRecalcNode(t.c1, recalclist);
addRecalcNode(t.c2, recalclist);
}
function turnTransistorOff(t){
function turnTransistorOff(t, recalclist){
if(!t.on) return;
if(ctrace && (traceTheseTransistors.indexOf(t.name)!=-1))
console.log(t.name, 'off', t.gate, t.c1, t.c2);
if(ctrace) console.log(t.name, 'off', t.gate, t.c1, t.c2);
t.on = false;
addRecalcNode(t.c1);
addRecalcNode(t.c2);
floatnode(t.c1);
floatnode(t.c2);
addRecalcNode(t.c1, recalclist);
addRecalcNode(t.c2, recalclist);
}
function addRecalcNode(nn){
if(nn==ngnd) return;
if(nn==npwr) return;
if(recalcHash[nn] == 1)return;
recalclist.push(nn);
recalcHash[nn] = 1;
function floatnode(nn){
if(nn==ngnd) return;
if(nn==npwr) return;
var n = nodes[nn];
if(n.state=='gnd') n.state = 'fl';
if(n.state=='pd') n.state = 'fl';
if(n.state=='vcc') n.state = 'fh';
if(n.state=='pu') n.state = 'fh';
if(ctrace) console.log('floating', nn, 'to', n.state);
}
function addRecalcNode(nn, recalclist){
if(nn==ngnd) return;
if(nn==npwr) return;
if(arrayContains(recalclist, nn)) return;
recalclist.push(nn);
// setAdd(recalclist, nn);
}
function getNodeGroup(i){
group = new Array();
addNodeToGroup(i);
var group = new Array();
addNodeToGroup(i, group);
return group;
}
function addNodeToGroup(i){
if(group.indexOf(i) != -1) return;
function addNodeToGroup(i, group){
if(arrayContains(group, i)) return;
group.push(i);
if(i==ngnd) return;
if(i==npwr) return;
nodes[i].c1c2s.forEach(
function(t){
if(!t.on) return;
var other;
if(t.c1==i) other=t.c2;
if(t.c2==i) other=t.c1;
addNodeToGroup(other);});
for(var t in nodes[i].c1c2s) addNodeTransistor(i, nodes[i].c1c2s[t], group);
}
function addNodeTransistor(node, t, group){
var tr = transistors[t];
if(!tr.on) return;
var other;
if(tr.c1==node) other=tr.c2;
if(tr.c2==node) other=tr.c1;
addNodeToGroup(other, group);
}
function getNodeValue(){
if(arrayContains(group, ngnd)) return false;
if(arrayContains(group, npwr)) return true;
function getNodeValue(group){
if(arrayContains(group, ngnd)) return 'gnd';
if(arrayContains(group, npwr)) return 'vcc';
var flstate;
for(var i in group){
var nn = group[i];
var n = nodes[nn];
if(n.pullup) return true;
if(n.pulldown) return false;
if(n.state) return true;
if(n.pullup) return 'pu';
if(n.pulldown) return 'pd';
if((n.state=='fl')&&(flstate==undefined)) flstate = 'fl';
if(n.state=='fh') flstate = 'fh';
}
return false;
if(flstate==undefined && ctrace) console.log(group);
return flstate;
}
function isNodeHigh(nn){
return(nodes[nn].state);
return arrayContains(['vcc','pu','fh'], nodes[nn].state);
}
function saveString(name, str){
@ -143,39 +150,30 @@ function saveString(name, str){
function allNodes(){
var res = new Array();
var ii = 0;
for(var i in nodes) {
// Don't feed numeric strings to recalcNodeList(). Numeric
// strings can cause a (data dependent) duplicate node number
// hiccup when accumulating a node group's list, ie:
// group => [ "49", 483, 49 ]
ii = Number( i );
if((ii!=npwr)&&(ii!=ngnd)) res.push(ii);
}
for(var i in nodes) if((i!=npwr)&&(i!=ngnd)) res.push(i);
return res;
}
function stateString(){
var codes = ['l','h'];
var codes = {gnd: 'g', vcc: 'v', pu: 'p', pd: 'd', fh: 'f', fl: 'l'};
var res = '';
for(var i=0;i<nodes.length;i++){
for(var i=0;i<1725;i++){
var n = nodes[i];
if(n==undefined) res+='x';
else if(i==ngnd) res+='g';
else if(i==npwr) res+='v';
else res+= codes[0+n.state];
else res+= codes[n.state];
}
return res;
}
function showState(str){
var codes = {g: false, h: true, v: true, l: false};
var codes = {g: 'gnd', v: 'vcc', p: 'pu', d: 'pd', f: 'fh', l: 'fl'};
for(var i=0;i<str.length;i++){
if(str[i]=='x') continue;
var state = codes[str[i]];
nodes[i].state = state;
nodes[i].state = codes[str[i]];
var gates = nodes[i].gates;
gates.forEach(function(t){t.on=state;});
for(var t in gates) transistors[gates[t]].on = isNodeHigh(i);
}
refresh();
}
@ -201,4 +199,12 @@ function setLow(name){
recalcNodeList([nn]);
}
function setAdd(arr, el){
var idx = ridx%(arr.length+1);
ridx+=131;
ridx%=123;
arr.splice(idx, 0, el);
return arr;
}
function arrayContains(arr, el){return arr.indexOf(el)!=-1;}

View File

@ -1,153 +0,0 @@
<!DOCTYPE html>
<head>
<title>Visual 6800 in JavaScript</title>
<style type="text/css">@import "expert.css";</style>
<script src="chip-6800/segdefs.js"></script>
<script src="chip-6800/transdefs.js"></script>
<script src="chip-6800/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-6800/support.js"></script>
<script src="chip-6800/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;
<a href="http://www.textfiles.com/programming/CARDS/6800">6800 instruction card</a>&nbsp;
<a href="http://www.sbprojects.com/sbasm/6800.htm#model">programming model</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>

File diff suppressed because one or more lines are too long

View File

@ -1,151 +0,0 @@
<!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>

View File

@ -1,228 +0,0 @@
/*
Copyright (c) 2010 Brian Silverman, Barry Silverman, Ed Spittles
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
body {
background: white;
color: black;
font-family :Verdana, Arial, Helvetica, Sans-Serif;
font-size: 12px;
}
#title {
font-size: 30px;
font-weight: bold;
}
div.frame {
margin-left: 10px;
min-width: 1120px; /* ugh - prevent memtable flowing underneath chip */
}
div.leftcolumn {
width: 804px; /* ugh - matches the div.chip width + border */
}
div.rightcolumn {
padding-left: 8px;
}
div.footer {
clear: both;
padding-top: 10px;
}
div.nochip {
display:none;
}
div#chipsurround {
height: 600px; /* matches the div.chip height */
}
div.chip {
background: lightgray;
border: 2px solid gray;
position: absolute; /* must be absolute to contain the canvas */
width: 800px;
height: 600px;
overflow: hidden;
}
canvas.chip {
position: absolute;
width: 600px; /* square chip image same height as div.chip */
height: 600px; /* square */
}
div.twobuttons{
float:left;
}
div.morebuttons{
float:left;
}
div.buttons{
/* top: -5px; */
}
div.status {
clear: left;
padding-top: 10px;
padding-bottom: 10px;
font-family: monospace;
font-size: 12px;
}
img.navbutton {
border: 0px;
}
img.navplay {
margin-right: 5px;
border: 0px;
}
img.navstop {
position: absolute;
border: 0px;
}
span.expertcheckbox {
margin-left: 20px;
}
table.memtable {
font-family: monospace;
font-size: 12px;
border-spacing: 0px;
overflow: auto;
}
div#layoutControlPanel{
display:none;
margin-top: 2px;
margin-bottom: 2px;
}
div#expertControlPanel{
display:none;
}
span.animatebox{
border:thin solid;
padding:2px;
border-color:gray;
}
a#linkHere{
padding:2px;
}
textarea#consolebox{
font-family:courier,monospace;
border: 1px solid gray;
margin: 2px;
padding: 2px;
width: 80em;
}
div#logstreamscroller{
overflow:auto;
}
table.logstream {
font-family: monospace;
font-size: 12px;
border-collapse: collapse;
text-align:center;
}
td {
padding-left: 3px;
padding-right: 3px;
}
td.header {
background-color: rgb(187, 204, 255); /* medium-dark blue */
}
td.oddcol {
background-color: rgb(227, 233, 255); /* light blue */
}
td.oddrow {
background-color: rgb(207, 218, 255); /* medium blue */
}
td.oddrowcol {
background-color: rgb(227, 233, 255); /* light blue */
}
/* Splitter */
#frame {
height: 750px;
}
div.leftcolumn, div.rightcolumn, {
overflow: auto;
}
div#righttopdiv, div#tracingdiv {
overflow: auto;
background-color: white;
}
div.rightcolumn {
background-color: white;
}
.vsplitbar {
width: 5px;
background: #aaa;
}
.vsplitbar {
width: 6px;
background: #669 url(3rdparty/img/vgrabber.gif) no-repeat center;
}
.vsplitbar:hover, .vsplitbar.active {
background: #c66 url(3rdparty/img/vgrabber.gif) no-repeat center;
opacity: 0.7;
filter: alpha(opacity=70); /* IE */
background: #c99;
}
.hsplitbar {
height: 6px;
background: #669 url(3rdparty/img/hgrabber.gif) no-repeat center;
}
.hsplitbar.active, .hsplitbar:hover {
background: #c66 url(3rdparty/img/hgrabber.gif) no-repeat center;
}
span#plain {
display: block;
margin-bottom: 4px;
}

View File

@ -1,152 +0,0 @@
<!DOCTYPE html>
<head>
<title>Visual 6502 in JavaScript</title>
<style type="text/css">@import "expert.css";</style>
<script src="segdefs.js"></script>
<script src="transdefs.js"></script>
<script src="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="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;
<a href="http://skilldrick.github.io/easy6502/#first-program">easy6502 assembler</a>&nbsp;
<a href="http://www.masswerk.at/6502/disassembler.html">mass:werk disassembler</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 '&gt;' to zoom in, 'x' or '&lt;' 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)" /><label for="updateShow1">(diffusion)</label>
<input type="checkbox" name="3" id="updateShow3" onchange="updateShow(this.name,this.checked)" /><label for="updateShow3">(grounded diffusion)</label>
<input type="checkbox" name="4" id="updateShow4" onchange="updateShow(this.name,this.checked)" /><label for="updateShow4">(powered diffusion)</label>
<input type="checkbox" name="5" id="updateShow5" onchange="updateShow(this.name,this.checked)" /><label for="updateShow5">(polysilicon)</label>
<input type="checkbox" name="0" id="updateShow0" onchange="updateShow(this.name,this.checked)" /><label for="updateShow0">(metal)</label>
<input type="checkbox" name="2" id="updateShow2" onchange="updateShow(this.name,this.checked)" /><label for="updateShow2">(protection)</label>
</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">
<label for="animateModeCheckbox">Animate during simulation:</label>
<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="https://web.archive.org/web/20210608195625/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>

View File

@ -1,646 +0,0 @@
/*
Copyright (c) 2010 Brian Silverman, Barry Silverman, Ed Spittles
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
var centerx=300, centery=300;
var zoom=1;
var dragMouseX, dragMouseY, moved;
var statbox;
var findThese;
var labelThese=[];
// Some constants for the graphics presentation
// the canvas is embedded in an 800x600 clipping div
// which gives rise to some of the 300 and 400 values in the code
// there are also some 600 values
// the 6502D chip coords are in the box (216,179) to (8983,9807)
// we have 4 canvases all the same size, now 2000 pixels square
// chip background - the layout
// overlay - a red/white transparency to show logic high or low
// hilite - to show the selected polygon
// hitbuffer - abusing color values to return which polygon is under a point
// we no longer use a scaling transform - we now scale the chip data at
// the point of drawing line segments
// if the canvas is any smaller than chip coordinates there will be
// rounding artifacts, and at high zoom there will be anti-aliasing on edges.
var grMaxZoom=12;
var grChipSize=10000;
var grChipOffsetX=400;
var grChipOffsetY=0;
var grCanvasSize=2000;
var grLineWidth=1;
// Index of layerNames corresponds to index into drawLayers
var layernames = ['metal', 'switched diffusion', 'inputdiode', 'grounded diffusion', 'powered diffusion', 'polysilicon'];
var colors = ['rgba(128,128,192,0.4)','#FFFF00','#FF00FF','#4DFF4D',
'#FF4D4D','#801AC0','rgba(128,0,255,0.75)'];
var drawlayers = [true, true, true, true, true, true];
// some modes and parameters which can be passed in from the URL query
var moveHereFirst;
var expertMode=true;
var animateChipLayout = true;
var userCode=[];
var userResetLow;
var userResetHigh;
var headlessSteps=1000;
var noSimulation=false;
var testprogram=[];
var testprogramAddress;
/////////////////////////
//
// Drawing Setup
//
/////////////////////////
// try to present a meaningful page before starting expensive work
function setup(){
statbox = document.getElementById('status');
setStatus('loading 6502...');
setTimeout(setup_part2, 0);
}
function setup_part2(){
frame = document.getElementById('frame');
statbox = document.getElementById('status');
// load the circuit before acting on URL parameters
setupNodes();
setupTransistors();
setupParams();
setupExpertMode();
detectOldBrowser();
setStatus('loading graphics...');
setTimeout(setup_part3, 0);
}
function setup_part3(){
if(chipLayoutIsVisible){
// if user requests no chip layout, we can skip all canvas operations
// which saves a lot of memory and allows us to run on small systems
updateChipLayoutVisibility(true);
}
setStatus('resetting ' + chipname + '...');
setTimeout(setup_part4, 0);
}
function setup_part4(){
setupTable();
setupNodeNameList();
logThese=signalSet(loglevel);
loadProgram();
setupConsole();
if(noSimulation){
stopChip();
running=undefined;
setStatus('Ready!');
} else {
initChip();
document.getElementById('stop').style.visibility = 'hidden';
go();
}
}
function detectOldBrowser(){
if(!("getBoundingClientRect" in document.documentElement)){
// simplify these functions (and adjust layout window position)
localx= function(el, gx){
return gx-el.offsetLeft;
}
localy= function(el, gy){
return gy-el.offsetTop;
}
document.getElementById('plain').style["float"]="right";
document.getElementById('chip').style.left=0;
document.getElementById('chip').style.top=0;
document.getElementById('chip').style.border=0;
}
}
function setupParams(){
if(location.search=="")
return
var queryParts=location.search.slice(1).split('&');
var panx;
var pany;
var zoom;
var userAddress;
for(var i=0;i<queryParts.length;i++){
var params=queryParts[i].split("=");
if(params.length!=2){
if(loglevel>0)
console.log('malformed parameters',params);
break;
}
var name=params[0];
var value=params[1].replace(/\/$/,""); // chrome sometimes adds trailing slash
// be (relatively) forgiving in what we accept
//
// user interface mode control
if(name=="loglevel" && parseInt(value)!=NaN){
updateLoglevel(value);
} else if(name=="logmore" && value!=""){
updateLogList(value);
} else if(name=="headlesssteps" && parseInt(value)!=NaN){
headlessSteps=parseInt(value);
} else if(name=="graphics" && value.indexOf("f")==0){
updateChipLayoutVisibility(false);
} else if(name=="canvas" && parseInt(value)!=NaN){
grCanvasSize=value;
// suppress simulation (for layout viewing only on slow browsers)
} else if(name=="nosim" && value.indexOf("t")==0){
noSimulation=true;
} else
// place the graphics window at a point of interest
if(name=="panx" && parseInt(value)!=NaN){
panx=parseInt(value);
} else if(name=="pany" && parseInt(value)!=NaN){
pany=parseInt(value);
} else if(name=="zoom" && parseInt(value)!=NaN){
zoom=parseInt(value);
} else
// perform a search, highlight and zoom to object(s)
if(name=="find" && value.length>0){
findThese=value;
} else
// affix label with optional box to highlight an area of interest
if(name=="label" && value.length>0){
labelThese.push(value.split(","));
} else
// load a test program: Address, Data and Reset
if(name=="a" && parseInt(value,16)!=NaN){
userAddress=parseInt(value,16);
} else if(name=="d" && value.match(/[0-9a-fA-F]*/)[0].length==value.length){
for(var j=0;j<value.length;j+=2)
userCode[userAddress++]=parseInt(value.slice(j,j+2),16);
} else if(name=="r" && parseInt(value,16)!=NaN){
userResetLow=parseInt(value,16)%256;
userResetHigh=(parseInt(value,16)>>8)%256;
} else
// setup input pin events, breakpoints, watchpoints
if(name=="reset0" && parseInt(value)!=NaN){
clockTriggers[value]=[clockTriggers[value],"setLow(nodenamereset);"].join("");
} else if(name=="reset1" && parseInt(value)!=NaN){
clockTriggers[value]=[clockTriggers[value],"setHigh(nodenamereset);"].join("");
} else if(name=="irq0" && parseInt(value)!=NaN){
clockTriggers[value]=[clockTriggers[value],"setLow('irq');"].join("");
} else if(name=="irq1" && parseInt(value)!=NaN){
clockTriggers[value]=[clockTriggers[value],"setHigh('irq');"].join("");
} else if(name=="nmi0" && parseInt(value)!=NaN){
clockTriggers[value]=[clockTriggers[value],"setLow('nmi');"].join("");
} else if(name=="nmi1" && parseInt(value)!=NaN){
clockTriggers[value]=[clockTriggers[value],"setHigh('nmi');"].join("");
} else if(name=="rdy0" && parseInt(value)!=NaN){
clockTriggers[value]=[clockTriggers[value],"setLow('rdy');"].join("");
} else if(name=="rdy1" && parseInt(value)!=NaN){
clockTriggers[value]=[clockTriggers[value],"setHigh('rdy');"].join("");
} else if(name=="so0" && parseInt(value)!=NaN){
clockTriggers[value]=[clockTriggers[value],"setLow('so');"].join("");
} else if(name=="so1" && parseInt(value)!=NaN){
clockTriggers[value]=[clockTriggers[value],"setHigh('so');"].join("");
// Some Z80 inputs - we can refactor if this becomes unwieldy
} else if(name=="int0" && parseInt(value)!=NaN){
clockTriggers[value]=[clockTriggers[value],"setLow('int');"].join("");
} else if(name=="int1" && parseInt(value)!=NaN){
clockTriggers[value]=[clockTriggers[value],"setHigh('int');"].join("");
} else if(name=="wait0" && parseInt(value)!=NaN){
clockTriggers[value]=[clockTriggers[value],"setLow('wait');"].join("");
} else if(name=="wait1" && parseInt(value)!=NaN){
clockTriggers[value]=[clockTriggers[value],"setHigh('wait');"].join("");
} else if(name=="busrq0" && parseInt(value)!=NaN){
clockTriggers[value]=[clockTriggers[value],"setLow('busrq');"].join("");
} else if(name=="busrq1" && parseInt(value)!=NaN){
clockTriggers[value]=[clockTriggers[value],"setHigh('busrq');"].join("");
//
} else if(name=="time" && parseInt(value)!=NaN){
eventTime=value;
} else if(name=="databus" && parseInt(value)!=NaN){
clockTriggers[eventTime]=[clockTriggers[eventTime],"writeDataBus(0x"+value+");"].join("");
} else
// run a test program, and optionally check against a golden checksum
if(name=="steps" && parseInt(value)!=NaN){
userSteps=parseInt(value);
running=true;
} else if(name=="checksum" && parseInt(value,16)!=NaN){
goldenChecksum=(0x100000000+parseInt(value,16)).toString(16).slice(-8);
} else {
if(loglevel>0)
console.log('unrecognised parameters:',params);
break;
}
}
if(panx!=null && pany!=null && zoom!=null)
moveHereFirst=[panx,pany,zoom];
}
function updateChipLayoutAnimation(isOn){
// simulation is much faster if we don't update the chip layout on every step
animateChipLayout=isOn;
document.getElementById('animateModeCheckbox').checked = animateChipLayout;
}
/////////////////////////
//
// User Interface
//
/////////////////////////
// these keyboard actions are primarily for the chip display
function handleKey(e){
var c = e.charCode || e.keyCode;
c = String.fromCharCode(c);
if('<>?npZzx'.indexOf(c)==-1) return;
if((c=='Z'||c=='x'||c=='<') && zoom>1) setZoom(zoom/1.2);
else if((c=='z'||c=='>') && zoom<grMaxZoom) setZoom(zoom*1.2);
else if(c=='?') setZoom(1);
// FIXME these keys are for the simulator (but not when focus is in a textbox)
else if(c=='n') stepForward();
else if(c=='p') stepBack();
}
// handler for zoom in/out using the mouse wheel
function handleWheelZoom(e){
chipsurround.focus();
e.preventDefault();
var n = e.deltaY / 100;
if(n>0 && zoom>1) setZoom(zoom/1.2);
if(n<0 && zoom<grMaxZoom) setZoom(zoom*1.2);
}
// handler for mousedown events over chip display
// must handle click-to-select (and focus), and drag to pan
function mouseDown(e){
chipsurround.focus();
e.preventDefault();
moved=false;
dragMouseX = e.clientX;
dragMouseY = e.clientY;
chipsurround.onmousemove = function(e){mouseMove(e)};
chipsurround.onmouseup = function(e){mouseUp(e)};
}
function mouseMove(e){
moved = true;
if(zoom==1) return;
var dx = e.clientX-dragMouseX;
var dy = e.clientY-dragMouseY;
dragMouseX = e.clientX;
dragMouseY = e.clientY;
centerx-=dx/zoom;
centerx = Math.max(centerx, 400/zoom);
centerx = Math.min(centerx, 600-400/zoom);
centery-=dy/zoom;
centery = Math.max(centery, 300/zoom);
centery = Math.min(centery, 600-300/zoom);
recenter();
}
function mouseUp(e){
if(!moved) handleClick(e);
chipsurround.onmousemove = undefined;
chipsurround.onmouseup = undefined;
}
function setZoom(n){
zoom = n;
setChipStyle({
width: 600*n+'px',
height: 600*n+'px'
});
recenter();
}
function recenter(){
var top = -centery*zoom+300;
top = Math.min(top, 0);
top = Math.max(top, -600*(zoom-1));
var left = -centerx*zoom+400;
left = Math.min(left, 0);
left = Math.max(left, (zoom==1)?100:-600*zoom+800);
setChipStyle({
top: top+'px',
left: left+'px',
});
updateLinkHere();
}
function updateLinkHere(){
var target = location.pathname + "?nosim=t&";
var findlist = document.getElementById('HighlightThese').value.split(/[\s,]+/).join(",");
if (findlist != "")
target = target + "find=" + findlist + "&";
target = target + whereAmIAsQuery();
document.getElementById('linkHere').href=target;
}
// place a text label on the highlight layer
// with an optional box around an area of interest
// coordinates used are those reported by a click
// for example:
// boxLabel(['PD', 50, 8424, 3536, 9256, 2464])
// boxLabel(['IR', 50, 8432, 2332, 9124, 984])
// boxLabel(['PLA', 100, 1169, 2328, 8393, 934])
// boxLabel(['Y', 50, 2143, 8820, 2317, 5689])
// boxLabel(['X', 50, 2317, 8820, 2490, 5689])
// boxLabel(['S', 50, 2490, 8820, 2814, 5689])
// boxLabel(['ALU', 50, 2814, 8820, 4525, 5689])
// boxLabel(['DAdj', 40, 4525, 8820, 5040, 5689])
// boxLabel(['A', 50, 5040, 8820, 5328, 5689])
// boxLabel(['PC', 50, 5559, 8820, 6819, 5689])
// boxLabel(['ID', 50, 7365, 8820, 7676, 5689])
// boxLabel(['TimC', 40, 600, 1926, 1174, 604])
function flashBoxLabel(args) {
clearHighlight();
var callBack = function(){boxLabel(args);};
setTimeout(callBack, 400);
setTimeout(clearHighlight, 800);
setTimeout(callBack, 1200);
}
function boxLabel(args) {
var text = args[0];
var textsize = args[1];
var thickness = 1+ textsize / 20;
var boxXmin = args[2] * grCanvasSize / grChipSize;
var boxYmin = args[3] * grCanvasSize / grChipSize;
var boxXmax = args[4] * grCanvasSize / grChipSize;
var boxYmax = args[5] * grCanvasSize / grChipSize;
ctx.lineWidth = thickness;
ctx.font = textsize + 'px sans-serif';
ctx.fillStyle = '#ff0'; // yellow
ctx.fillStyle = '#f8f'; // magenta
ctx.fillStyle = '#fff'; // white
ctx.strokeStyle = '#fff'; // white
if(args.length>4){
ctxDrawBox(ctx, boxXmin, boxYmin, boxXmax, boxYmax);
// offset the text label to the interior of the box
boxYmin -= thickness * 2;
}
ctx.strokeStyle = '#fff'; // white
ctx.strokeStyle = '#000'; // black
ctx.lineWidth = thickness*2;
ctx.strokeText(text, boxXmin, boxYmin);
ctx.fillText(text, boxXmin, boxYmin);
}
var highlightThese;
// flash some set of nodes according to user input
// also zoom to fit those nodes (not presently optional)
function hiliteNodeList(){
var tmplist = document.getElementById('HighlightThese').value.split(/[\s,]+/);
if(tmplist.join("").length==0){
// request to highlight nothing, so switch off any signal highlighting
hiliteNode(-1);
return;
}
highlightThese = [];
var seglist=[];
var report="";
for(var i=0;i<tmplist.length;i++){
// get a node number from a signal name or a node number
var name = tmplist[i];
var value = parseInt(tmplist[i]);
if((value!=NaN) && (typeof nodes[value] != "undefined")) {
highlightThese.push(value);
report="node: " + value + ' ' + nodeName(value);
for(var s in nodes[value].segs)
seglist.push(nodes[value].segs[s]);
} else if(typeof nodenames[name] != "undefined") {
highlightThese.push(nodenames[name]);
report="node: " + nodenames[name] + ' ' + name;
for(var s in nodes[nodenames[name]].segs)
seglist.push(nodes[nodenames[name]].segs[s]);
} else if(typeof transistors[name] != "undefined") {
// normally we push numbers: a non-number is a transistor name
highlightThese.push(name);
report="transistor: " + name;
seglist.push([
transistors[name].bb[0],transistors[name].bb[2],
transistors[name].bb[1],transistors[name].bb[3]
]);
} else {
// allow match of underscore-delimited components, so
// SUMS and dpc17 both match the node dpc17_SUMS
for(var i in nodenames){
re=new RegExp("(^" + name + "_|_" + name + "$)");
if (re.test(i)){
value = nodenames[i];
highlightThese.push(value);
report="node: " + value + ' ' + nodeName(value);
for(var s in nodes[value].segs)
seglist.push(nodes[value].segs[s]);
break;
}
}
}
}
if(highlightThese.length==0){
setStatus('Find: nothing found!','(Enter a list of nodenumbers, names or transistor names)');
return;
} else if (highlightThese.length==1){
setStatus('Find results:',report);
} else {
setStatus('Find: multiple objects found','(' + highlightThese.length + ' objects)');
}
var xmin=seglist[0][0], xmax=seglist[0][0];
var ymin=seglist[0][1], ymax=seglist[0][1];
for(var s in seglist){
for(var i=0;i<seglist[s].length;i+=2){
if(seglist[s][i]<xmin) xmin=seglist[s][i];
if(seglist[s][i]>xmax) xmax=seglist[s][i];
if(seglist[s][i+1]<ymin) ymin=seglist[s][i+1];
if(seglist[s][i+1]>ymax) ymax=seglist[s][i+1];
}
}
zoomToBox(xmin,xmax,ymin,ymax);
updateLinkHere();
clearHighlight(); // nullify the simulation overlay (orange/purple)
hiliteNode(-1); // unhighlight all nodes
setTimeout("hiliteNode(highlightThese);", 400);
setTimeout("hiliteNode(-1);", 800);
setTimeout("hiliteNode(highlightThese);", 1200);
}
// some notes on coordinates:
// the localx and localy functions return canvas coordinate offsets from the canvas window top left corner
// we divide the results by 'zoom' to get drawn coordinates useful in findNodeNumber
// to convert to reported user chip coordinates we multiply by grChipSize/600
// to compare to segdefs and transdefs coordinates we subtract grChipOffsetX from x and subtract y from grChipSize plus grChipOffsetY
function handleClick(e){
var x = localx(hilite, e.clientX)/zoom;
var y = localy(hilite, e.clientY)/zoom;
var w = findNodeNumber(x,y);
// convert to chip coordinates
var cx = Math.round(x*grChipSize/600);
var cy = Math.round(y*grChipSize/600);
// prepare two lines of status report
var s1='x: ' + (cx - grChipOffsetX) + ' y: ' + (cy - grChipOffsetY);
var s2='node:&nbsp;' + w + '&nbsp;' + nodeName(w);
if(w==-1) {
setStatus(s1); // no node found, so report only coordinates
return;
}
// we have a node, but maybe we clicked over a transistor
var nodelist=[w];
// match the coordinate against transistor gate bounding boxes
x=cx-grChipOffsetX;
y=grChipSize+grChipOffsetY-cy;
for(var i=0;i<nodes[w].gates.length;i++){
var xmin=nodes[w].gates[i].bb[0], xmax=nodes[w].gates[i].bb[1];
var ymin=nodes[w].gates[i].bb[2], ymax=nodes[w].gates[i].bb[3];
if((x >= xmin) && (x <= xmax) && (y >= ymin) && (y <= ymax)){
// only one match at most, so we replace rather than push
nodelist=[nodes[w].gates[i].name];
s2='transistor: ' + nodes[w].gates[i].name + ' on ' + s2;
}
}
// if this is a shift-click, just find and highlight the pass-connected group
// and list the nodes (or nodenames, preferably)
if(e.shiftKey) {
getNodeGroup(w);
nodelist = group;
s2 = "nodegroup from&nbsp;" + s2 +
" (nodes:&nbsp;" +
group.map(function(x){return nodeName(x)?nodeName(x):x;}).join(",") +
")";
}
hiliteNode(nodelist);
setStatus(s1, s2);
if(ctrace) console.log(s1, s2);
}
function updateLoglevel(value){
loglevel = value;
logThese = signalSet(loglevel);
initLogbox(logThese);
}
function setupExpertMode(isOn){
document.getElementById('expertControlPanel').style.display = 'block';
if(loglevel==0)
updateLoglevel(1);
if(chipLayoutIsVisible)
document.getElementById('layoutControlPanel').style.display = 'block';
}
var consolegetc; // global variable to hold last keypress in the console area
var consolebox;
function setupConsole(){
consolebox=document.getElementById('consolebox');
consolebox.onkeypress=function(e){consolegetc=e.charCode || e.keyCode;};
}
var chipsurround;
function updateChipLayoutVisibility(isOn){
chipLayoutIsVisible=isOn;
if(chipLayoutIsVisible) {
updateChipLayoutAnimation(true);
// resize the two panes appropriately
$("#frame").trigger("resize", [ 810 ]);
$("#rightcolumn").trigger("resize", [ 738 - 180 ]);
// replace the Show Chip button with the chip graphics
chipsurround=document.getElementById('chipsurround');
chipsurround.style.display = 'block';
document.getElementById('layoutControlPanel').style.display = 'block';
document.getElementById('nochip').style.display = 'none';
// allow the browser to respond while we load the graphics
setStatus('loading graphics...');
setTimeout(setupChipLayoutGraphics, 0);
} else {
// cannot animate the layout if there is no canvas
updateChipLayoutAnimation(false);
// resize the two panes appropriately
$("#frame").trigger("resize", [ 120 ]);
$("#rightcolumn").trigger("resize", [ 200 ]);
// replace the layout display with a button to show it
document.getElementById('chipsurround').style.display = 'none';
document.getElementById('layoutControlPanel').style.display = 'none';
document.getElementById('nochip').style.display = 'block';
}
}
function setupChipLayoutGraphics(){
setupLayerVisibility();
setupBackground();
setupOverlay();
setupHilite();
setupHitBuffer();
recenter();
refresh();
document.getElementById('waiting').style.display = 'none';
setStatus('Ready!'); // would prefer chipStatus but it's not idempotent
// pre-fill the Find box if parameters supplied
if(typeof findThese != "undefined") {
document.getElementById('HighlightThese').value = findThese;
hiliteNodeList(); // will pan and zoom to fit
}
// pre-pan and zoom if requested (will override any zoom-to-fit by hiliteNodeList)
if(moveHereFirst!=null)
moveHere(moveHereFirst);
// draw any URL-requested labels and boxes
if(labelThese.length>0) {
for(var i=0;i<labelThese.length;i+=1)
flashBoxLabel(labelThese[i]);
}
// grant focus to the chip display to enable zoom keys
chipsurround.focus();
chipsurround.onwheel = function(e){handleWheelZoom(e);};
chipsurround.onmousedown = function(e){mouseDown(e);};
chipsurround.onkeypress = function(e){handleKey(e);};
chipsurround.onmouseout = function(e){mouseLeave(e);};
}
// utility function to save graphics pan and zoom
function whereAmIAsQuery(){
var w=whereAmI();
return "panx="+w[0].toFixed(1)+"&pany="+w[1].toFixed(1)+"&zoom="+w[2].toFixed(1);
}
function whereAmI(){
return [centerx, centery, zoom];
}
// restore graphics pan and zoom (perhaps as given in the URL)
function moveHere(place){
centerx = place[0];
centery = place[1];
setZoom(place[2]);
}
/////////////////////////
//
// Etc.
//
/////////////////////////
function setChipStyle(props){
for(var i in props){
chipbg.style[i] = props[i];
overlay.style[i] = props[i];
hilite.style[i] = props[i];
hitbuffer.style[i] = props[i];
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 321 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 319 B

View File

@ -2,25 +2,17 @@
<head>
<title>Visual 6502 in JavaScript</title>
<!-- by default, index.html will run in kiosk mode -->
<style type="text/css">@import "kiosk.css";</style>
<style type="text/css">@import "wires.css";</style>
<script src="segdefs.js"></script>
<script src="transdefs.js"></script>
<script src="nodenames.js"></script>
<script src="kioskWires.js"></script>
<script src="wires.js"></script>
<script src="chipsim.js"></script>
<script src="memtable.js"></script>
<script src="macros.js"></script>
<script src="testprogram.js"></script>
<script type="text/javascript">
function handleOnload() {
// two checks and fixes here:
// - replace the dynamic content with an image if running older versions of IE
// - redirect to the expert page if we find any query parameters
//
/MSIE (\d+\.\d+);/.test(navigator.appVersion);
IEVersion=Number(RegExp.$1);
if((navigator.appName == 'Microsoft Internet Explorer') && (IEVersion<9)){
@ -28,20 +20,7 @@ function handleOnload() {
'<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{
var suffix=location.search;
var path=location.pathname;
// ensure we always have a trailing slash
path=path.replace("index.html","").replace(/\/?$/,"/");
if (suffix != "") {
// redirect to the expert page
var prefix=location.protocol+"//"+location.host+path;
window.location.replace(prefix+"expert.html"+suffix);
return;
} else {
// normal case: start the simulator
setTimeout(setup,200);
}
setTimeout(setup,200);
}
}
</script>
@ -62,11 +41,11 @@ lots of RAM. If you have trouble, please <a href="browsertrouble.html">check com
<br />
<span id="browsertrouble"></span>
<br />
Keyboard controls: 'z' to zoom in, 'x' to zoom out, 'n' to step the simulation.
Hit '>' to zoom in, '<' to zoom out
<br />
Mouse controls: Left-click and drag to scroll around (when you're zoomed in.)
Left-click and drag to scroll around
<br />
More information in the <a href="https://web.archive.org/web/20210608195625/http://visual6502.org/wiki/index.php?title=JssimUserHelp">User Guide</a>.
Enter your own program into the array of RAM
<br />
<br />
</span>
@ -79,15 +58,14 @@ More information in the <a href="https://web.archive.org/web/20210608195625/http
</div>
<div class = "buttons">
<div style="position:relative; float:left;">
<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="start"></a>
<a href ="javascript:stopChip()"id="stop"><img class="navstop" src="images/stop.png"></a>
<a href ="javascript:runChip()" id="start"><img class="navplay" src="images/play.png"></a>
</div>
<div style="float:left;">
<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="step"></a>
<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 style="float:right; margin-left:20px;">... or try <a href="expert.html">Advanced</a></div>
</div>
<p class="status" id="status">x: 0<br>y: 0</p>
<table class="memtable" id="memtable"></table>
@ -97,10 +75,10 @@ More information in the <a href="https://web.archive.org/web/20210608195625/http
<br />
<br />
Source code is available on <a href="http://github.com/trebonian/visual6502">github visual6502</a>.
Use the online <a href="https://skilldrick.github.io/easy6502/#first-program">emulator and assembler</a> from the easy6502 tutorial
and <a href="http://www.masswerk.at/6502/disassembler.html">disassembler</a> from mass:werk
Use the online <a href="http://www.6502asm.com/">emulator and assembler</a> from 6502asm.com
and <a href="http://www.e-tradition.net/bytes/6502/disassembler.html">disassembler</a> from e-tradition.net
<br />
For in-depth 6502 investigation and some more advanced features, try our <a href="expert.html">Advanced</a> page.
For in-depth 6502 investigation and some more advanced features, try our <a href="/stage/JSSim/index.html">Experimenter's (Beta) version</a>.
<br />
<br />

View File

@ -1,202 +0,0 @@
/*
Copyright (c) 2010 Brian Silverman, Barry Silverman
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
var centerx=300, centery=300;
var zoom=1;
var dragMouseX, dragMouseY, moved;
var statbox;
var animateChipLayout = true;
var userCode=[];
var userResetLow;
var userResetHigh;
// Some constants for the graphics presentation
// the canvas is embedded in an 800x600 clipping div
// which gives rise to some of the 300 and 400 values in the code
// there are also some 600 values
// the 6502D chip coords are in the box (216,179) to (8983,9807)
// we have 4 canvases all the same size, now 2000 pixels square
// chip background - the layout
// overlay - a red/white transparency to show logic high or low
// hilite - to show the selected polygon
// hitbuffer - abusing color values to return which polygon is under a point
// we no longer use a scaling transform - we now scale the chip data at
// the point of drawing line segments
// if the canvas is any smaller than chip coordinates there will be
// rounding artifacts, and at high zoom there will be anti-aliasing on edges.
var grMaxZoom=12;
var grChipSize=10000;
var grChipOffsetX=400;
var grChipOffsetY=0;
var grCanvasSize=2000;
var grLineWidth=1;
// Index of layerNames corresponds to index into drawLayers
var layernames = ['metal', 'switched diffusion', 'inputdiode', 'grounded diffusion', 'powered diffusion', 'polysilicon'];
var colors = ['rgba(128,128,192,0.4)','#FFFF00','#FF00FF','#4DFF4D',
'#FF4D4D','#801AC0','rgba(128,0,255,0.75)'];
var drawlayers = [true, true, true, true, true, true];
/////////////////////////
//
// Drawing Setup
//
/////////////////////////
// try to present a meaningful page before starting expensive work
function setup(){
statbox = document.getElementById('status');
setStatus('loading 6502...');
setTimeout(setup_part2, 0);
}
function setup_part2(){
frame = document.getElementById('frame');
statbox = document.getElementById('status');
setupNodes();
setupTransistors();
setupLayerVisibility();
setupBackground();
setupOverlay();
setupHilite();
setupHitBuffer();
recenter();
refresh();
setupTable();
window.onkeypress = function(e){handleKey(e);}
hilite.onmousedown = function(e){mouseDown(e);}
setStatus('resetting 6502...');
setTimeout(setup_part3, 0);
}
function setup_part3(){
loadProgram();
writeTriggers={}; // kiosk mode does not handle I/O
initChip();
document.getElementById('stop').style.visibility = 'hidden';
go();
}
/////////////////////////
//
// User Interface
//
/////////////////////////
function handleKey(e){
var c = e.charCode || e.keyCode;
c = String.fromCharCode(c);
if('zx<>?np'.indexOf(c)==-1) return;
if((c=='x' || c=='<') && zoom>1) setZoom(zoom/1.2);
else if((c=='z' || c=='>') && zoom<grMaxZoom) setZoom(zoom*1.2);
else if(c=='?') setZoom(1);
else if(c=='n') stepForward();
else if(c=='p') stepBack();
}
function mouseDown(e){
e.preventDefault();
moved=false;
dragMouseX = e.clientX;
dragMouseY = e.clientY;
window.onmousemove = function(e){mouseMove(e)};
window.onmouseup = function(e){mouseUp(e)};
}
function mouseMove(e){
moved = true;
if(zoom==1) return;
var dx = e.clientX-dragMouseX;
var dy = e.clientY-dragMouseY;
dragMouseX = e.clientX;
dragMouseY = e.clientY;
centerx-=dx/zoom;
centerx = Math.max(centerx, 400/zoom);
centerx = Math.min(centerx, 600-400/zoom);
centery-=dy/zoom;
centery = Math.max(centery, 300/zoom);
centery = Math.min(centery, 600-300/zoom);
recenter();
}
function mouseUp(e){
if(!moved) handleClick(e);
window.onmousemove = undefined;
window.onmouseup = undefined;
}
function setZoom(n){
zoom = n;
setChipStyle({
width: 600*n+'px',
height: 600*n+'px'
});
recenter();
}
function recenter(){
var top = -centery*zoom+300;
top = Math.min(top, 0);
top = Math.max(top, -600*(zoom-1));
var left = -centerx*zoom+400;
left = Math.min(left, 0);
left = Math.max(left, (zoom==1)?100:-600*zoom+800);
setChipStyle({
top: top+'px',
left: left+'px',
});
}
function handleClick(e){
var x = localx(hilite, e.clientX)/zoom;
var y = localy(hilite, e.clientY)/zoom;
var w = findNodeNumber(x,y);
if(e.shiftKey) {
getNodeGroup(w);
hiliteNode(group);
}
else {var a=new Array(); a.push(w); hiliteNode(a);}
var cx = Math.round(x*grChipSize/600);
var cy = Math.round(y*grChipSize/600);
if(w==-1) setStatus('x:',cx,'<br>','y:',cy);
else {
var s1='x: ' + cx + ' y: ' + cy;
var s2='node: ' + w + ' ' + nodeName(w);
setStatus(s1, s2);
}
}
/////////////////////////
//
// Etc.
//
/////////////////////////
function setChipStyle(props){
for(var i in props){
chipbg.style[i] = props[i];
overlay.style[i] = props[i];
hilite.style[i] = props[i];
hitbuffer.style[i] = props[i];
}
}

680
macros.js
View File

@ -1,5 +1,5 @@
/*
Copyright (c) 2010 Brian Silverman, Barry Silverman, Ed Spittles, Achim Breidenbach
Copyright (c) 2010 Brian Silverman, Barry Silverman
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@ -21,82 +21,30 @@
*/
var memory = Array();
var code = [0xa9, 0x00, 0x20, 0x10, 0x00, 0x4c, 0x02, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xe8, 0x88, 0xe6, 0x40, 0x38, 0x69, 0x02, 0x60];
var cycle = 0;
var trace = Array();
var logstream = Array();
var running = false;
var logThese=[];
var chipname='6502';
var nodenamereset='res';
var presetLogLists=[
['cycle'],
['ab','db','rw','Fetch','pc','a','x','y','s','p'],
['Execute','State'],
['ir','tcstate','-pd'],
['adl','adh','sb','alu'],
['alucin','alua','alub','alucout','aluvout','dasb'],
['plaOutputs','DPControl'],
['idb','dor'],
['irq','nmi',nodenamereset],
];
function loadProgram(){
// a moderate size of static testprogram might be loaded
if(testprogram.length!=0 && testprogramAddress != undefined)
for(var i=0;testprogram[i]!=undefined;i++){
var a=testprogramAddress+i;
mWrite(a, testprogram[i]);
if(a<0x200)
setCellValue(a, testprogram[i]);
}
// a small test program or patch might be passed in the URL
if(userCode.length!=0)
for(var i=0;i<userCode.length;i++){
if(userCode[i] != undefined){
mWrite(i, userCode[i]);
if(i<0x200)
setCellValue(i, userCode[i]);
}
}
// default reset vector will be 0x0000 because undefined memory reads as zero
if(userResetLow!=undefined)
mWrite(0xfffc, userResetLow);
if(userResetHigh!=undefined)
mWrite(0xfffd, userResetHigh);
function go(n){
for(var i=0;i<code.length;i++){
mWrite(i, code[i]);
setCellValue(i, code[i]);
}
mWrite(0xfffc, 0x00);
mWrite(0xfffd, 0x00);
steps();
}
function go(){
if(typeof userSteps != "undefined"){
if(--userSteps==0){
running=false;
userSteps=undefined;
}
}
function steps(){
if(running) {
step();
setTimeout(go, 0); // schedule the next poll
setTimeout(steps, 0); // schedule the next poll
}
}
function goUntilSync(){
halfStep();
while(!isNodeHigh(nodenames['sync']) || isNodeHigh(nodenames['clk0']))
halfStep();
}
function goUntilSyncOrWrite(){
halfStep();
cycle++;
while(
!isNodeHigh(nodenames['clk0']) ||
( !isNodeHigh(nodenames['sync']) && isNodeHigh(nodenames['rw']) )
) {
halfStep();
cycle++;
}
chipStatus();
}
function testNMI(n){
initChip();
@ -137,118 +85,56 @@ function testNMI(n){
for(var i=0;i<16;i++){step();}
}
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 nn in nodes) nodes[nn].state = 'fl';
nodes[ngnd].state = 'gnd';
nodes[npwr].state = 'vcc';
for(var tn in transistors) transistors[tn].on = false;
setLow(nodenamereset);
setLow('res');
setLow('clk0');
setHigh('rdy'); setLow('so');
setHigh('irq'); setHigh('nmi');
recalcNodeList(allNodes());
for(var i=0;i<8;i++){setHigh('clk0'), setLow('clk0');}
setHigh(nodenamereset);
for(var i=0;i<18;i++){halfStep();} // avoid updating graphics and trace buffer before user code
setHigh('res');
for(var i=0;i<18;i++){resetStep();}
refresh();
cycle = 0;
trace = Array();
if(typeof expertMode != "undefined")
updateLogList();
chipStatus();
if(ctrace)console.log('initChip done after', now()-start);
}
function signalSet(n){
var signals=[];
for (var i=0; (i<=n)&&(i<presetLogLists.length) ; i++){
for (var j=0; j<presetLogLists[i].length; j++){
signals.push(presetLogLists[i][j]);
}
}
return signals;
}
function updateLogList(names){
// user supplied a list of signals, which we append to the set defined by loglevel
logThese = signalSet(loglevel);
if(typeof names == "undefined")
// this is a UI call - read the text input
names = document.getElementById('LogThese').value;
else
// this is an URL call - update the text input box
document.getElementById('LogThese').value = names;
names = names.split(/[\s,]+/);
for(var i=0;i<names.length;i++){
// could be a signal name, a node number, or a special name
if(typeof busToString(names[i]) != "undefined")
logThese.push(names[i]);
}
initLogbox(logThese);
}
var traceChecksum='';
var goldenChecksum;
// simulate a single clock phase, updating trace and highlighting layout
function step(){
var s=stateString();
var m=getMem();
trace[cycle]= {chip: s, mem: m};
if(goldenChecksum != undefined)
traceChecksum=adler32(traceChecksum+s+m.slice(0,511).toString(16));
trace[cycle]= {chip: stateString(), mem: getMem()};
halfStep();
if(animateChipLayout)
refresh();
cycle++;
chipStatus();
}
// triggers for breakpoints, watchpoints, input pin events
// almost always are undefined when tested, so minimal impact on performance
clockTriggers={};
writeTriggers={};
readTriggers={};
fetchTriggers={};
// example instruction tracing triggers
// fetchTriggers[0x20]="console.log('0x'+readAddressBus().toString(16)+': JSR');";
// fetchTriggers[0x60]="console.log('0x'+readAddressBus().toString(16)+': RTS');";
// fetchTriggers[0x4c]="console.log('0x'+readAddressBus().toString(16)+': JMP');";
// simulate a single clock phase with no update to graphics or trace
function halfStep(){
var clk = isNodeHigh(nodenames['clk0']);
if (clk) {setLow('clk0'); handleBusRead(); }
else {setHigh('clk0'); handleBusWrite();}
eval(clockTriggers[cycle+1]); // pre-apply next tick's inputs now, so the updates are displayed
refresh();
}
function resetStep(){
var clk = isNodeHigh(nodenames['clk0']);
if (clk) {setLow('clk0'); handleBusRead(); }
else {setHigh('clk0'); handleBusWrite();}
}
function handleBusRead(){
if(isNodeHigh(nodenames['rw'])){
var a = readAddressBus();
var d = eval(readTriggers[a]);
if(d == undefined)
d = mRead(readAddressBus());
if(isNodeHigh(nodenames['sync']))
eval(fetchTriggers[d]);
writeDataBus(d);
}
if(isNodeHigh(nodenames['rw'])) writeDataBus(mRead(readAddressBus()));
}
function handleBusWrite(){
if(!isNodeHigh(nodenames['rw'])){
var a = readAddressBus();
var d = readDataBus();
eval(writeTriggers[a]);
mWrite(a,d);
if(a<0x200) setCellValue(a,d);
}
@ -264,8 +150,8 @@ function readPstring(){
var result;
result = (isNodeHigh(nodenames['p7'])?'N':'n') +
(isNodeHigh(nodenames['p6'])?'V':'v') +
'&#8209' + // non-breaking hyphen
(isNodeHigh(nodenames['p4'])?'B':'b') +
'-' +
(isNodeHigh(nodenames['p3'])?'B':'b') +
(isNodeHigh(nodenames['p3'])?'D':'d') +
(isNodeHigh(nodenames['p2'])?'I':'i') +
(isNodeHigh(nodenames['p1'])?'Z':'z') +
@ -277,98 +163,6 @@ function readPC(){return (readBits('pch', 8)<<8) + readBits('pcl', 8);}
function readPCL(){return readBits('pcl', 8);}
function readPCH(){return readBits('pch', 8);}
// for one-hot or few-hot signal collections we want to list the active ones
// and for brevity we remove the common prefix
function listActiveSignals(pattern){
var r=new RegExp(pattern);
var list=[];
for(var i in nodenamelist){
if(r.test(nodenamelist[i])) {
if(isNodeHigh(nodenames[nodenamelist[i]]))
// also map hyphen to a non-breaking version
list.push(nodenamelist[i].replace(r,'').replace(/-/g,'&#8209'));
}
}
return list;
}
// The 6502 TCState is almost but not quite an inverted one-hot shift register
function listActiveTCStates() {
var s=[];
if(!isNodeHigh(nodenames['clock1'])) s.push("T0");
if(!isNodeHigh(nodenames['clock2'])) s.push("T1");
if(!isNodeHigh(nodenames['t2'])) s.push("T2");
if(!isNodeHigh(nodenames['t3'])) s.push("T3");
if(!isNodeHigh(nodenames['t4'])) s.push("T4");
if(!isNodeHigh(nodenames['t5'])) s.push("T5");
return s.join("+");
}
// Show all time code node states (active and inactive) in fixed format,
// with non-PLA-controlling internal state indication in square
// brackets, followed by RCL-resident timing state indication.
// ".." for a PLA-controlling node indicates inactive state, "T"* for a
// PLA-controlling node indicates active state.
// Bracketed codes are one of T1/V0/T6/..
// V0 indicates the VEC0 node, T6 is a synonym for the VEC1 node.
// The RCL codes are one of SD1/SD2/...
// For discussion of this reconstruction, see:
// http://visual6502.org/wiki/index.php?title=6502_Timing_States
function allTCStates( useHTML )
{
var s = "";
var _spc;
useHTML = (typeof useHTML === 'undefined') ? false : useHTML;
// Use Non-Breaking Space for presentation in an HTML (browser)
// context, else use ASCII space for logging context
_spc = useHTML ? '&nbsp;' : ' ';
if ( !isNodeHigh( nodenames[ 'clock1' ] ) ) s += "T0"; else s += "..";
s += _spc;
// T+ in visual6502 is called T1x in
// http://www.weihenstephan.org/~michaste/pagetable/6502/6502.jpg
// Notated as T+ for compatibility with PLA node names
if ( !isNodeHigh( nodenames[ 'clock2' ] ) ) s += "T+"; else s += "..";
s += _spc;
if ( !isNodeHigh( nodenames[ 't2' ] ) ) s += "T2"; else s += "..";
s += _spc;
if ( !isNodeHigh( nodenames[ 't3' ] ) ) s += "T3"; else s += "..";
s += _spc;
if ( !isNodeHigh( nodenames[ 't4' ] ) ) s += "T4"; else s += "..";
s += _spc;
if ( !isNodeHigh( nodenames[ 't5' ] ) ) s += "T5"; else s += "..";
s += _spc + "[";
// Check three confirmed exclusive states (three nodes)
if ( isNodeHigh( 862 ) ) {
s += "T1";
// ...else if VEC0 is on...
} else if ( isNodeHigh( nodenames[ 'VEC0' ] ) ) {
// ...then tell the outside world
s += "V0";
// ...else if VEC1 is on...
} else if ( isNodeHigh( nodenames[ 'VEC1' ] ) ) {
// ...then this is the canonical T6. It is a synonym for VEC1
s += "T6";
} else {
// ...else none of the "hidden" bits in the clock state is active
s += "..";
}
s += "]" + _spc;
// Check the RCL's two confirmed exclusive states (two nodes)
// If this node is grounding ~WR...
if ( isNodeHigh( 440 ) ) {
// ...then we can regard this state as Store Data 1
s += "SD1";
// ...else if this node is grounding ~WR...
} else if ( isNodeHigh( 1258 ) ) {
// ...then we can regard this state as Store Data 2
s += "SD2";
} else {
// ...else none of the RCL-resident timing bits is active
s += "...";
}
return s;
}
function readBit(name){
return isNodeHigh(nodenames[name])?1:0;
}
@ -381,72 +175,6 @@ function readBits(name, n){
return res;
}
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=='pc')
return busToHex('pch') + busToHex('pcl');
if(busname=='p')
return readPstring();
if(busname=='tcstate')
return ['clock1','clock2','t2','t3','t4','t5'].map(busToHex).join("");
if(busname=='State')
return listActiveTCStates();
if(busname=='TState')
return allTCStates( true );
if(busname=='Phi')
// Pretty-printed phase indication based on the state of cp1,
// the internal Phase 1 node
return '&Phi;' +
(isNodeHigh( nodenames[ 'cp1' ] ) ? '1' : '2');
if(busname=='Execute')
return disassemblytoHTML(readBits('ir',8));
if(busname=='Fetch')
return isNodeHigh(nodenames['sync'])?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 busToHex(busname){
// may be passed a bus or a signal, so allow multiple signals
var width=0;
var r=new RegExp('^' + busname + '[0-9]+$');
for(var i in nodenamelist){
if(r.test(nodenamelist[i])) {
width++;
}
}
if(width==0) {
// not a bus, so could be a signal, a nodenumber or a mistake
if(typeof nodenames[busname] != "undefined")
return isNodeHigh(nodenames[busname])?"1":"0";
if((parseInt(busname)!=NaN) && (typeof nodes[busname] != "undefined"))
return isNodeHigh(busname)?"1":"0";
return undefined;
}
if(width>16)
return undefined;
// finally, convert from logic values to hex
return (0x10000+readBits(busname,width)).toString(16).slice(-(width-1)/4-1);
}
function writeDataBus(x){
var recalcs = Array();
for(var i=0;i<8;i++){
@ -467,11 +195,12 @@ function mRead(a){
function mWrite(a, d){memory[a]=d;}
function clkNodes(){
var res = Array();
res.push(943);
for(var i in nodes[943].gates){
var t = nodes[943].gates[i];
var t = transistors[nodes[943].gates[i]];
if(t.c1==npwr) res.push(t.c2);
if(t.c2==npwr) res.push(t.c1);
}
@ -483,10 +212,8 @@ function runChip(){
var stop = document.getElementById('stop');
start.style.visibility = 'hidden';
stop.style.visibility = 'visible';
if(typeof running == "undefined")
initChip();
running = true;
go();
steps();
}
function stopChip(){
@ -499,13 +226,11 @@ function stopChip(){
function resetChip(){
stopChip();
setStatus('resetting ' + chipname + '...');
setStatus('resetting 6502...');
setTimeout(initChip,0);
}
function stepForward(){
if(typeof running == "undefined")
initChip();
stopChip();
step();
}
@ -534,147 +259,50 @@ function chipStatus(){
' Y:' + hexByte(readY()) +
' SP:' + hexByte(readSP()) +
' ' + readPstring();
var machine3 =
'Hz: ' + estimatedHz().toFixed(1);
if(typeof expertMode != "undefined") {
machine3 += ' Exec: ' + busToString('Execute') + '(' + busToString('State') + ')';
if(isNodeHigh(nodenames['sync']))
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);
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 + "<br>Hz: " + estimatedHz().toFixed(1));
if (loglevel>2 && ctrace) {
console.log(machine1 + " " + machine2 + " " + machine3 + " " + machine4 + " " + machine5);
}
selectCell(ab);
}
// run for an extended number of cycles, with low overhead, for interactive programs or for benchmarking
// note: to run an interactive program, use an URL like
// http://visual6502.org/JSSim/expert.html?graphics=f&loglevel=-1&headlesssteps=-500
function goFor(){
var n = headlessSteps; // a negative value is a request to free-run
if(headlessSteps<0)
n=-n;
var start = document.getElementById('start');
var stop = document.getElementById('stop');
start.style.visibility = 'hidden';
stop.style.visibility = 'visible';
if(typeof running == "undefined") {
initChip();
}
running = true;
setTimeout("instantaneousHz(); goForN("+n+")",0);
}
// helper function: allows us to poll 'running' without resetting it when we're re-scheduled
function goForN(n){
var n2=n; // save our parameter so we can re-submit ourselves
while(n--){
halfStep();
cycle++;
}
instantaneousHz();
chipStatus();
if((headlessSteps<0) && running){
setTimeout("goForN("+n2+")",0); // re-submit ourselves if we are meant to free-run
return;
}
running = false;
var start = document.getElementById('start');
var stop = document.getElementById('stop');
start.style.visibility = 'visible';
stop.style.visibility = 'hidden';
}
var prevHzTimeStamp=0;
var prevHzCycleCount=0;
var prevHzEstimate1=1;
var prevHzEstimate2=1;
var HzSamplingRate=10;
// return an averaged speed: called periodically during normal running
function estimatedHz(){
if(cycle%HzSamplingRate!=3)
return prevHzEstimate1;
var HzTimeStamp = now();
var HzEstimate = (cycle-prevHzCycleCount+.01)/(HzTimeStamp-prevHzTimeStamp+.01);
HzEstimate=HzEstimate*1000/2; // convert from phases per millisecond to Hz
if(HzEstimate<5)
HzSamplingRate=5; // quicker
if(HzEstimate>10)
HzSamplingRate=10; // smoother
prevHzEstimate2=prevHzEstimate1;
prevHzEstimate1=(HzEstimate+prevHzEstimate1+prevHzEstimate2)/3; // wrong way to average speeds
prevHzTimeStamp=HzTimeStamp;
prevHzCycleCount=cycle;
return prevHzEstimate1
if(cycle%HzSamplingRate!=3)
return prevHzEstimate1;
var HzTimeStamp = now();
var HzEstimate = (cycle-prevHzCycleCount+.01)/(HzTimeStamp-prevHzTimeStamp+.01);
HzEstimate=HzEstimate*1000/2; // convert from phases per millisecond to Hz
if(HzEstimate<5)
HzSamplingRate=5; // quicker
if(HzEstimate>10)
HzSamplingRate=10; // smoother
prevHzEstimate2=prevHzEstimate1;
prevHzEstimate1=(HzEstimate+prevHzEstimate1+prevHzEstimate2)/3; // wrong way to average speeds
prevHzTimeStamp=HzTimeStamp;
prevHzCycleCount=cycle;
return prevHzEstimate1
}
// return instantaneous speed: called twice, before and after a timed run using goFor()
function instantaneousHz(){
var HzTimeStamp = now();
var HzEstimate = (cycle-prevHzCycleCount+.01)/(HzTimeStamp-prevHzTimeStamp+.01);
HzEstimate=HzEstimate*1000/2; // convert from phases per millisecond to Hz
prevHzEstimate1=HzEstimate;
prevHzEstimate2=prevHzEstimate1;
prevHzTimeStamp=HzTimeStamp;
prevHzCycleCount=cycle;
return prevHzEstimate1
}
var logbox;
function initLogbox(names){
logbox=document.getElementById('logstream');
if(logbox==null)return;
names=names.map(function(x){return x.replace(/^-/,'')});
logStream = [];
logStream.push("<td class=header>" + names.join("</td><td class=header>") + "</td>");
logbox.innerHTML = "<tr>"+logStream.join("</tr><tr>")+"</tr>";
}
var logboxAppend=true;
// can append or prepend new states to the log table
// when we reverse direction we need to reorder the log stream
function updateLogDirection(){
var loglines=[];
logboxAppend=!logboxAppend;
// the first element is the header so we can't reverse()
for (var i=1;i<logStream.length;i++) {
loglines.unshift(logStream[i]);
}
loglines.unshift(logStream[0]);
logStream=loglines;
logbox.innerHTML = "<tr>"+logStream.join("</tr><tr>")+"</tr>";
}
// update the table of signal values, by prepending or appending
function updateLogbox(names){
var signals=[];
var odd=true;
var bg;
var row;
for(var i in names){
if(cycle % 4 < 2){
bg = odd ? " class=oddcol":"";
} else {
bg = odd ? " class=oddrow":" class=oddrowcol";
}
signals.push("<td" + bg + ">" + busToString(names[i]) + "</td>");
odd =! odd;
}
row = "<tr>" + signals.join("") + "</tr>";
if(logboxAppend)
logStream.push(row);
else
logStream.splice(1,0,row);
logbox.innerHTML = logStream.join("");
}
function getMem(){
var res = Array();
@ -688,177 +316,3 @@ function setMem(arr){
function hexWord(n){return (0x10000+n).toString(16).substring(1)}
function hexByte(n){return (0x100+n).toString(16).substring(1)}
function adler32(x){
var a=1;
var b=0;
for(var i=0;i<x.length;i++){
a=(a+x.charCodeAt(i))%65521;
b=(b+a)%65521;
}
return (0x100000000+(b<<16)+a).toString(16).slice(-8);
}
// sanitised opcode for HTML output
function disassemblytoHTML(byte){
var opcode=disassembly[byte];
if(typeof opcode == "undefined")
return "unknown"
return opcode.replace(/ /,'&nbsp;');
}
// opcode lookup for 6502 - not quite a disassembly
// javascript derived from Debugger.java by Achim Breidenbach
var disassembly={
0x00:"BRK",
0x01:"ORA (zp,X)",
0x05:"ORA zp",
0x06:"ASL zp",
0x08:"PHP",
0x09:"ORA #",
0x0A:"ASL ",
0x0D:"ORA Abs",
0x0E:"ASL Abs",
0x10:"BPL ",
0x11:"ORA (zp),Y",
0x15:"ORA zp,X",
0x16:"ASL zp,X",
0x18:"CLC",
0x19:"ORA Abs,Y",
0x1D:"ORA Abs,X",
0x1E:"ASL Abs,X",
0x20:"JSR Abs",
0x21:"AND (zp,X)",
0x24:"BIT zp",
0x25:"AND zp",
0x26:"ROL zp",
0x28:"PLP",
0x29:"AND #",
0x2A:"ROL ",
0x2C:"BIT Abs",
0x2D:"AND Abs",
0x2E:"ROL Abs",
0x30:"BMI ",
0x31:"AND (zp),Y",
0x35:"AND zp,X",
0x36:"ROL zp,X",
0x38:"SEC",
0x39:"AND Abs,Y",
0x3D:"AND Abs,X",
0x3E:"ROL Abs,X",
0x40:"RTI",
0x41:"EOR (zp,X)",
0x45:"EOR zp",
0x46:"LSR zp",
0x48:"PHA",
0x49:"EOR #",
0x4A:"LSR ",
0x4C:"JMP Abs",
0x4D:"EOR Abs",
0x4E:"LSR Abs",
0x50:"BVC ",
0x51:"EOR (zp),Y",
0x55:"EOR zp,X",
0x56:"LSR zp,X",
0x58:"CLI",
0x59:"EOR Abs,Y",
0x5D:"EOR Abs,X",
0x5E:"LSR Abs,X",
0x60:"RTS",
0x61:"ADC (zp,X)",
0x65:"ADC zp",
0x66:"ROR zp",
0x68:"PLA",
0x69:"ADC #",
0x6A:"ROR ",
0x6C:"JMP (Abs)",
0x6D:"ADC Abs",
0x6E:"ROR Abs",
0x70:"BVS ",
0x71:"ADC (zp),Y",
0x75:"ADC zp,X",
0x76:"ROR zp,X",
0x78:"SEI",
0x79:"ADC Abs,Y",
0x7D:"ADC Abs,X",
0x7E:"ROR Abs,X",
0x81:"STA (zp,X)",
0x84:"STY zp",
0x85:"STA zp",
0x86:"STX zp",
0x88:"DEY",
0x8A:"TXA",
0x8C:"STY Abs",
0x8D:"STA Abs",
0x8E:"STX Abs",
0x90:"BCC ",
0x91:"STA (zp),Y",
0x94:"STY zp,X",
0x95:"STA zp,X",
0x96:"STX zp,Y",
0x98:"TYA",
0x99:"STA Abs,Y",
0x9A:"TXS",
0x9D:"STA Abs,X",
0xA0:"LDY #",
0xA1:"LDA (zp,X)",
0xA2:"LDX #",
0xA4:"LDY zp",
0xA5:"LDA zp",
0xA6:"LDX zp",
0xA8:"TAY",
0xA9:"LDA #",
0xAA:"TAX",
0xAC:"LDY Abs",
0xAD:"LDA Abs",
0xAE:"LDX Abs",
0xB0:"BCS ",
0xB1:"LDA (zp),Y",
0xB4:"LDY zp,X",
0xB5:"LDA zp,X",
0xB6:"LDX zp,Y",
0xB8:"CLV",
0xB9:"LDA Abs,Y",
0xBA:"TSX",
0xBC:"LDY Abs,X",
0xBD:"LDA Abs,X",
0xBE:"LDX Abs,Y",
0xC0:"CPY #",
0xC1:"CMP (zp,X)",
0xC4:"CPY zp",
0xC5:"CMP zp",
0xC6:"DEC zp",
0xC8:"INY",
0xC9:"CMP #",
0xCA:"DEX",
0xCC:"CPY Abs",
0xCD:"CMP Abs",
0xCE:"DEC Abs",
0xD0:"BNE ",
0xD1:"CMP (zp),Y",
0xD5:"CMP zp,X",
0xD6:"DEC zp,X",
0xD8:"CLD",
0xD9:"CMP Abs,Y",
0xDD:"CMP Abs,X",
0xDE:"DEC Abs,X",
0xE0:"CPX #",
0xE1:"SBC (zp,X)",
0xE4:"CPX zp",
0xE5:"SBC zp",
0xE6:"INC zp",
0xE8:"INX",
0xE9:"SBC #",
0xEA:"NOP",
0xEC:"CPX Abs",
0xED:"SBC Abs",
0xEE:"INC Abs",
0xF0:"BEQ ",
0xF1:"SBC (zp),Y",
0xF5:"SBC zp,X",
0xF6:"INC zp,X",
0xF8:"SED",
0xF9:"SBC Abs,Y",
0xFD:"SBC Abs,X",
0xFE:"INC Abs,X",
};

View File

@ -59,9 +59,7 @@ function cellKeydown(e){
}
function setCellValue(n, val){
if(val==undefined)
val=0x00;
val%=256;
val%=256;
cellEl(n).val=val;
cellEl(n).innerHTML=hexByte(val);
}
@ -73,7 +71,7 @@ function selectCell(n){
if(n>=0x200) return;
cellEl(n).style.background = '#ff8';
selected = n;
table.onkeydown = function(e){cellKeydown(e);};
window.onkeydown = function(e){cellKeydown(e);};
}
function unselectCell(){

View File

@ -1,5 +1,5 @@
/*
Copyright (c) 2010 Brian Silverman, Barry Silverman, Ed Spittles, Segher Boessenkool
Copyright (c) 2010 Brian Silverman, Barry Silverman, Ed Spittles
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@ -82,7 +82,7 @@ x4: 85,
x5: 589,
x6: 448,
x7: 777,
pcl0: 1139, // machine state: program counter low (first storage node output)
pcl0: 1139, // machine state: program counter low (first storage node)
pcl1: 1022,
pcl2: 655,
pcl3: 1359,
@ -90,30 +90,14 @@ pcl4: 900,
pcl5: 622,
pcl6: 377,
pcl7: 1611,
pclp0: 488, // machine state: program counter low (pre-incremented?, second storage node)
pclp1: 976,
pclp2: 481,
pclp3: 723,
pclp4: 208,
pclp5: 72,
pclp6: 1458,
pclp7: 1647,
"#pclp0": 1227, // machine state: program counter low (pre-incremented?, inverse second storage node)
"~pclp0": 1227, // automatic alias replacing hash with tilde
"#pclp1": 1102,
"~pclp1": 1102, // automatic alias replacing hash with tilde
"#pclp2": 1079,
"~pclp2": 1079, // automatic alias replacing hash with tilde
"#pclp3": 868,
"~pclp3": 868, // automatic alias replacing hash with tilde
"#pclp4": 39,
"~pclp4": 39, // automatic alias replacing hash with tilde
"#pclp5": 1326,
"~pclp5": 1326, // automatic alias replacing hash with tilde
"#pclp6": 731,
"~pclp6": 731, // automatic alias replacing hash with tilde
"#pclp7": 536,
"~pclp7": 536, // automatic alias replacing hash with tilde
pclp0: 526, // machine state: program counter low (pre-incremented?, second storage node)
pclp1: 1102,
pclp2: 1411,
pclp3: 868,
pclp4: 15,
pclp5: 1326,
pclp6: 993,
pclp7: 536,
pch0: 1670, // machine state: program counter high (first storage node)
pch1: 292,
pch2: 502,
@ -122,50 +106,22 @@ pch4: 948,
pch5: 49,
pch6: 1551,
pch7: 205,
pchp0: 1722, // machine state: program counter high (pre-incremented?, second storage node output)
pchp1: 209,
pchp2: 1496,
pchp3: 141,
pchp4: 27,
pchp5: 1301,
pchp6: 652,
pchp7: 1206,
"#pchp0": 780, // machine state: program counter high (pre-incremented?, inverse second storage node)
"~pchp0": 780, // automatic alias replacing hash with tilde
"#pchp1": 113,
"~pchp1": 113, // automatic alias replacing hash with tilde
"#pchp2": 114,
"~pchp2": 114, // automatic alias replacing hash with tilde
"#pchp3": 124,
"~pchp3": 124, // automatic alias replacing hash with tilde
"#pchp4": 820,
"~pchp4": 820, // automatic alias replacing hash with tilde
"#pchp5": 33,
"~pchp5": 33, // automatic alias replacing hash with tilde
"#pchp6": 751,
"~pchp6": 751, // automatic alias replacing hash with tilde
"#pchp7": 535,
"~pchp7": 535, // automatic alias replacing hash with tilde
// machine state: status register (not the storage nodes)
p0: 32, // C bit of status register (storage node)
p1: 627, // Z bit of status register (storage node)
p2: 1553, // I bit of status register (storage node)
p3: 348, // D bit of status register (storage node)
p4: 1119, // there is no bit4 in the status register! (not a storage node)
p5: -1, // there is no bit5 in the status register! (not a storage node)
p6: 1625, // V bit of status register (storage node)
p7: 69, // N bit of status register (storage node)
// internal bus: status register outputs for push P
Pout0: 687,
Pout1: 1444,
Pout2: 1421,
Pout3: 439,
Pout4: 1119, // there is no bit4 in the status register!
Pout5: -1, // there is no bit5 in the status register!
Pout6: 77,
Pout7: 1370,
pchp0: 780, // machine state: program counter high (pre-incremented?, second storage node)
pchp1: 126,
pchp2: 114,
pchp3: 1061,
pchp4: 820,
pchp5: 469,
pchp6: 751,
pchp7: 663,
p0: 687, // machine state: status register
p1: 1444,
p2: 1421,
p3: 439,
p4: 1119, // there is no bit4 in the status register!
p5: -1, // there is no bit5 in the status register!
p6: 77,
p7: 1370,
s0: 1403, // machine state: stack pointer
s1: 183,
s2: 81,
@ -190,31 +146,13 @@ notir4: 26,
notir5: 1394,
notir6: 895,
notir7: 1320,
irline3: 996, // internal signal: PLA input - ir0 OR ir1
clock1: 1536, // internal state: timing control aka #T0
clock1: 1536, // automatic alias replacing hash with tilde
clock2: 156, // internal state: timing control aka #T+
clock2: 156, // automatic alias replacing hash with tilde
irline3: 996, // internal signal: PLA input - ir0 AND ir1
clock1: 156, // internal state: timing control
clock2: 1536, // internal state: timing control
t2: 971, // internal state: timing control
t3: 1567,
t4: 690,
t5: 909,
noty0: 1025, // datapath state: not Y register
noty1: 1138,
noty2: 1484,
noty3: 184,
noty4: 565,
noty5: 981,
noty6: 1439,
noty7: 1640,
notx0: 987, // datapath state: not X register
notx1: 1434,
notx2: 890,
notx3: 1521,
notx4: 485,
notx5: 1017,
notx6: 730,
notx7: 1561,
nots0: 418, // datapath state: not stack pointer
nots1: 1064,
nots2: 752,
@ -247,8 +185,7 @@ sb4: 1405,
sb5: 166,
sb6: 1336,
sb7: 1001,
notalu0: 394, // datapath state: alu output storage node (inverse) aka #ADD0
notalu0: 394, // automatic alias replacing hash with tilde
notalu0: 394, // datapath state: alu output storage node (inverse)
notalu1: 697,
notalu2: 276,
notalu3: 495,
@ -256,7 +193,7 @@ notalu4: 1490,
notalu5: 893,
notalu6: 68,
notalu7: 1123,
alu0: 401, // datapath signal: ALU output aka ADD0out
alu0: 401, // datapath signal: ALU output
alu1: 872,
alu2: 1637,
alu3: 1414,
@ -273,7 +210,7 @@ dasb4: 1405, // same node as sb4
dasb5: 263,
dasb6: 679,
dasb7: 1494,
adl0: 413, // internal bus: address low
adl0: 413, // internal state: address latch low
adl1: 1282,
adl2: 1242,
adl3: 684,
@ -281,7 +218,7 @@ adl4: 1437,
adl5: 1630,
adl6: 121,
adl7: 1299,
adh0: 407, // internal bus: address high
adh0: 407, // internal state: address latch high
adh1: 52,
adh2: 1651,
adh3: 315,
@ -289,7 +226,7 @@ adh4: 1160,
adh5: 483,
adh6: 13,
adh7: 1539,
idb0: 1108, // internal bus: data bus
idb0: 1108, // internal state: data buffer
idb1: 991,
idb2: 1473,
idb3: 1302,
@ -313,15 +250,7 @@ dor4: 1088,
dor5: 1453,
dor6: 1415,
dor7: 63,
"pd0.clearIR": 1622, // internal state: predecode register output (anded with not ClearIR)
"pd1.clearIR": 809,
"pd2.clearIR": 1671,
"pd3.clearIR": 1587,
"pd4.clearIR": 540,
"pd5.clearIR": 667,
"pd6.clearIR": 1460,
"pd7.clearIR": 1410,
pd0: 758, // internal state: predecode register (storage node)
pd0: 758, // internal state: predecode register
pd1: 361,
pd2: 955,
pd3: 894,
@ -329,304 +258,180 @@ pd4: 369,
pd5: 829,
pd6: 1669,
pd7: 1690,
// internal signals: predecode latch partial decodes
"PD-xxxx10x0": 1019,
"PD-1xx000x0": 1294,
"PD-0xx0xx0x": 365,
"PD-xxx010x1": 302,
"PD-n-0xx0xx0x": 125,
"#TWOCYCLE": 851,
"~TWOCYCLE": 851, // automatic alias replacing hash with tilde
"#TWOCYCLE.phi1": 792,
"~TWOCYCLE.phi1": 792, // automatic alias replacing hash with tilde
"ONEBYTE": 778,
abl0: 1096, // internal bus: address bus low latched data out (inverse of inverted storage node)
abl1: 376,
abl2: 1502,
abl3: 1250,
abl4: 1232,
abl5: 234,
abl6: 178,
abl7: 567,
"#ABL0": 153, // internal state: address bus low latched data out (storage node, inverted)
"~ABL0": 153, // automatic alias replacing hash with tilde
"#ABL1": 107,
"~ABL1": 107, // automatic alias replacing hash with tilde
"#ABL2": 707,
"~ABL2": 707, // automatic alias replacing hash with tilde
"#ABL3": 825,
"~ABL3": 825, // automatic alias replacing hash with tilde
"#ABL4": 364,
"~ABL4": 364, // automatic alias replacing hash with tilde
"#ABL5": 1513,
"~ABL5": 1513, // automatic alias replacing hash with tilde
"#ABL6": 1307,
"~ABL6": 1307, // automatic alias replacing hash with tilde
"#ABL7": 28,
"~ABL7": 28, // automatic alias replacing hash with tilde
abh0: 1429, // internal bus: address bus high latched data out (inverse of inverted storage node)
abh1: 713,
abh2: 287,
abh3: 422,
abh4: 1143,
abh5: 775,
abh6: 997,
abh7: 489,
"#ABH0": 1062, // internal state: address bus high latched data out (storage node, inverted)
"~ABH0": 1062, // automatic alias replacing hash with tilde
"#ABH1": 907,
"~ABH1": 907, // automatic alias replacing hash with tilde
"#ABH2": 768,
"~ABH2": 768, // automatic alias replacing hash with tilde
"#ABH3": 92,
"~ABH3": 92, // automatic alias replacing hash with tilde
"#ABH4": 668,
"~ABH4": 668, // automatic alias replacing hash with tilde
"#ABH5": 1128,
"~ABH5": 1128, // automatic alias replacing hash with tilde
"#ABH6": 289,
"~ABH6": 289, // automatic alias replacing hash with tilde
"#ABH7": 429,
"~ABH7": 429, // automatic alias replacing hash with tilde
"branch-back": 626, // distinguish forward from backward branches
"branch-forward.phi1": 1110, // distinguish forward from backward branches
"branch-back.phi1": 771, // distinguish forward from backward branches in IPC logic
notRdy0: 248, // internal signal: global pipeline control
"notRdy0.phi1": 1272, // delayed pipeline control
"notRdy0.delay": 770, // global pipeline control latched by phi1 and then phi2
"#notRdy0.delay": 559, // global pipeline control latched by phi1 and then phi2 (storage node)
"~notRdy0.delay": 559, // automatic alias replacing hash with tilde
notRdy0: 248, // internal signal: global pipeline control
Reset0: 67, // internal signal: retimed reset from pin
C1x5Reset: 926, // retimed and pipelined reset in progress
notRnWprepad: 187, // internal signal: to pad, yet to be inverted and retimed
RnWstretched: 353, // internal signal: control datapad output drivers, aka TRISTATE
"#DBE": 1035, // internal signal: formerly from DBE pad (6501)
"~DBE": 1035, // automatic alias replacing hash with tilde
RnWstretched: 353, // internal signal: control datapad output drivers
cp1: 710, // internal signal: clock phase 1
cclk: 943, // unbonded pad: internal non-overlapping phi2
cclk: 943, // unbonded pad: internal non-overlappying phi2
fetch: 879, // internal signal
clearIR: 1077, // internal signal
D1x1: 827, // internal signal: interrupt handler related
H1x1: 1042, // internal signal: drive status byte onto databus
// internal signal: pla outputs block 1 (west/left edge of die)
// often 130 pla outputs are mentioned - we have 131 here
"op-sty/cpy-mem": 1601, // pla0
"op-T3-ind-y": 60, // pla1
"op-T2-abs-y": 1512, // pla2
"op-T0-iny/dey": 382, // pla3
"x-op-T0-tya": 1173, // pla4
"op-T0-cpy/iny": 1233, // pla5
pla0: 1601,
pla1: 60,
pla2: 1512,
pla3: 382,
pla4: 1173,
pla5: 1233,
// internal signal: pla outputs block 2
"op-T2-idx-x-xy": 258, // pla6
"op-xy": 1562, // pla7
"op-T2-ind-x": 84, // pla8
"x-op-T0-txa": 1543, // pla9
"op-T0-dex": 76, // pla10
"op-T0-cpx/inx": 1658, // pla11
"op-from-x": 1540, // pla12
"op-T0-txs": 245, // pla13
"op-T0-ldx/tax/tsx": 985, // pla14
"op-T+-dex": 786, // pla15
"op-T+-inx": 1664, // pla16
"op-T0-tsx": 682, // pla17
"op-T+-iny/dey": 1482, // pla18
"op-T0-ldy-mem": 665, // pla19
"op-T0-tay/ldy-not-idx": 286, // pla20
pla6: 258,
pla7: 1562,
pla8: 84,
pla9: 1543,
pla10: 76,
pla11: 1658,
pla12: 1540,
pla13: 245,
pla14: 985,
pla15: 786,
pla16: 1664,
pla17: 682,
pla18: 1482,
pla19: 665,
pla20: 286,
// internal signal: pla outputs block 3
// not pla, feed through
"op-T0-jsr": 271, // pla21
"op-T5-brk": 370, // pla22
"op-T0-php/pha": 552, // pla23
"op-T4-rts": 1612, // pla24
"op-T3-plp/pla": 1487, // pla25
"op-T5-rti": 784, // pla26
"op-ror": 244, // pla27
"op-T2": 788, // pla28
"op-T0-eor": 1623, // pla29
"op-jmp": 764, // pla30
"op-T2-abs": 1057, // pla31
"op-T0-ora": 403, // pla32
"op-T2-ADL/ADD":204, // pla33
"op-T0":1273, // pla34
"op-T2-stack":1582, // pla35
"op-T3-stack/bit/jmp":1031, // pla36
pla21: 271,
pla22: 370,
pla23: 552,
pla24: 1612,
pla25: 1487,
pla26: 784,
pla27: 244,
pla28: 788,
pla29: 1623,
pla30: 764,
pla31: 1057,
pla32: 403,
pla33: 204,
pla34: 1273,
pla35: 1582,
pla36: 1031,
// internal signal: pla outputs block 4
"op-T4-brk/jsr":804, // pla37
"op-T4-rti":1311, // pla38
"op-T3-ind-x":1428, // pla39
"op-T4-ind-y":492, // pla40
"op-T2-ind-y":1204, // pla41
"op-T3-abs-idx":58, // pla42
"op-plp/pla":1520, // pla43
"op-inc/nop":324, // pla44
"op-T4-ind-x":1259, // pla45
"x-op-T3-ind-y":342, // pla46
"op-rti/rts":857, // pla47
"op-T2-jsr":712, // pla48
"op-T0-cpx/cpy/inx/iny":1337, // pla49
"op-T0-cmp":1355, // pla50
"op-T0-sbc":787, // pla51 // 52:111XXXXX 1 0 T0SBC
"op-T0-adc/sbc":575, // pla52 // 51:X11XXXXX 1 0 T0ADCSBC
"op-rol/ror":1466, // pla53
pla37: 804,
pla38: 1311,
pla39: 1428,
pla40: 492,
pla41: 1204,
pla42: 58,
pla43: 1520,
pla44: 324,
pla45: 1259,
pla46: 342,
pla47: 857,
pla48: 712,
pla49: 1337,
pla50: 1355,
pla51_T0SBC: 787, // 52:111XXXXX 1 0 T0SBC
pla52_T0ADCSBC: 575, // 51:X11XXXXX 1 0 T0ADCSBC
pla53: 1466,
// internal signal: pla outputs block 5
"op-T3-jmp":1381, // pla54
"op-shift":546, // pla55
"op-T5-jsr":776, // pla56
"op-T2-stack-access":157, // pla57
"op-T0-tya":257, // pla58
"op-T+-ora/and/eor/adc":1243, // pla59
"op-T+-adc/sbc":822, // pla60
"op-T+-shift-a":1324, // pla61
"op-T0-txa":179, // pla62
"op-T0-pla":131, // pla63
"op-T0-lda":1420, // pla64
"op-T0-acc":1342, // pla65
"op-T0-tay":4, // pla66
"op-T0-shift-a":1396, // pla67
"op-T0-tax":167, // pla68
"op-T0-bit":303, // pla69
"op-T0-and":1504, // pla70
"op-T4-abs-idx":354, // pla71
"op-T5-ind-y":1168, // pla72
pla54: 1381,
pla55: 546,
pla56: 776,
pla57: 157,
pla58: 257,
pla59: 1243,
pla60: 822,
pla61: 1324,
pla62: 179,
pla63: 131,
pla64: 1420,
pla65: 1342,
pla66: 4,
pla67: 1396,
pla68: 167,
pla69: 303,
pla70: 1504,
pla71: 354,
pla72: 1168,
// internal signal: pla outputs block 6
"op-branch-done":1721, // pla73 // has extra non-pla input
"op-T2-pha":1086, // pla74
"op-T0-shift-right-a":1074, // pla75
"op-shift-right":1246, // pla76
"op-T2-brk":487, // pla77
"op-T3-jsr":579, // pla78
"op-sta/cmp":145, // pla79
"op-T2-branch":1239, // pla80 // T2BR, 83 for Balazs
"op-T2-zp/zp-idx":285, // pla81
pla73: 1721, // has extra non-pla input
pla74: 1086,
pla75: 1074,
pla76: 1246,
pla77: 487,
pla78: 579,
pla79: 145,
pla80_T2BR: 1239, // T2BR, 83 for Balazs
pla81: 285,
// not pla, feed through
// not pla, feed through
"op-T2-ind":1524, // pla82
"op-T2-abs-access":273, // pla83 // has extra pulldown: pla97
"op-T5-rts":0, // pla84
"op-T4":341, // pla85
"op-T3":120, // pla86
"op-T0-brk/rti":1478, // pla87
"op-T0-jmp":594, // pla88
"op-T5-ind-x":1210, // pla89
"op-T3-abs/idx/ind":677, // pla90 // has extra pulldown: pla97
pla82: 1524,
pla83: 273, // has extra pulldown: pla97
pla84: 0,
pla85: 341,
pla86: 120,
pla87: 1478,
pla88: 594,
pla89: 1210,
pla90: 677, // has extra pulldown: pla97
// internal signal: pla outputs block 7
"x-op-T4-ind-y":461, // pla91
"x-op-T3-abs-idx":447, // pla92
"op-T3-branch":660, // pla93
"op-brk/rti":1557, // pla94
"op-jsr":259, // pla95
"x-op-jmp":1052, // pla96
pla91: 461,
pla92: 447,
pla93: 660,
pla94: 1557,
pla95: 259,
pla96: 1052,
// gap
"op-push/pull":791, // pla97 // feeds into pla83 and pla90 (no normal pla output)
"op-store":517, // pla98
"op-T4-brk":352, // pla99
"op-T2-php":750, // pla100
"op-T2-php/pha":932, // pla101
"op-T4-jmp":1589, // pla102
pla97: 791, // feeds into pla83 and pla90 (no normal pla output)
pla98: 517,
pla99: 352,
pla100: 750,
pla101: 932,
pla102: 1589,
// gap
"op-T5-rti/rts":446, // pla103
"xx-op-T5-jsr":528, // pla104
pla103: 446,
pla104: 528,
// internal signal: pla outputs block 8
"op-T2-jmp-abs":309, // pla105
"x-op-T3-plp/pla":1430, // pla106
"op-lsr/ror/dec/inc":53, // pla107
"op-asl/rol":691, // pla108
"op-T0-cli/sei":1292, // pla109
pla105: 309,
pla106: 1430,
pla107: 53,
pla108: 691,
pla109: 1292,
// gap
"op-T+-bit":1646, // pla110
"op-T0-clc/sec":1114, // pla111
"op-T3-mem-zp-idx":904, // pla112
"x-op-T+-adc/sbc":1155, // pla113
"x-op-T0-bit":1476, // pla114
"op-T0-plp":1226, // pla115
"x-op-T4-rti":1569, // pla116
"op-T+-cmp":301, // pla117
"op-T+-cpx/cpy-abs":950, // pla118
"op-T+-asl/rol-a":1665, // pla119
pla110: 1646,
pla111: 1114,
pla112: 904,
pla113: 1155,
pla114: 1476,
pla115: 1226,
pla116: 1569,
pla117: 301,
pla118: 950,
pla119: 1665,
// internal signal: pla outputs block 9
"op-T+-cpx/cpy-imm/zp":1710, // pla120
"x-op-push/pull":1050, // pla121 // feeds into pla130 (no normal pla output)
"op-T0-cld/sed":1419, // pla122
"#op-branch-bit6":840, // pla123 // IR bit6 used only to detect branch type
"~op-branch-bit6":840, // automatic alias replacing hash with tilde
"op-T3-mem-abs":607, // pla124
"op-T2-mem-zp":219, // pla125
"op-T5-mem-ind-idx":1385, // pla126
"op-T4-mem-abs-idx":281, // pla127
"#op-branch-bit7":1174, // pla128 // IR bit7 used only to detect branch type
"~op-branch-bit7":1174, // automatic alias replacing hash with tilde
"op-clv":1164, // pla129
"op-implied":1006, // pla130 // has extra pulldowns: pla121 and ir0
// internal signals: derived from pla outputs
"#op-branch-done": 1048,
"~op-branch-done": 1048, // automatic alias replacing hash with tilde
"#op-T3-branch": 1708,
"~op-T3-branch": 1708, // automatic alias replacing hash with tilde
"op-ANDS": 1228,
"op-EORS": 1689,
"op-ORS": 522,
"op-SUMS": 1196,
"op-SRS": 934,
"#op-store": 925,
"~op-store": 925, // automatic alias replacing hash with tilde
"#WR": 1352,
"~WR": 1352, // automatic alias replacing hash with tilde
"op-rmw": 434,
"short-circuit-idx-add": 1185,
"short-circuit-branch-add": 430,
"#op-set-C": 252,
"~op-set-C": 252, // automatic alias replacing hash with tilde
pla120: 1710,
pla121: 1050, // feeds into pla130 (no normal pla output)
pla122: 1419,
pla123: 840,
pla124: 607,
pla125: 219,
pla126: 1385,
pla127: 281,
pla128: 1174,
pla129: 1164,
pla130: 1006, // has extra pulldowns: pla121 and ir0
// internal signals: control signals
nnT2BR: 967, // doubly inverted
"#BRtaken": 1544, // aka #TAKEN
"~BRtaken": 1544, // automatic alias replacing hash with tilde
// internal signals and state: interrupt and vector related
// segher says:
// "P" are the latched external signals.
// "G" are the signals that actually trigger the interrupt.
// "NMIL" is to do the edge detection -- it's pretty much just a delayed NMIG.
// INTG is IRQ and NMI taken together.
IRQP: 675,
"#IRQP": 888,
"~IRQP": 888, // automatic alias replacing hash with tilde
NMIP: 1032,
"#NMIP": 297,
"~NMIP": 297, // automatic alias replacing hash with tilde
"#NMIG": 264,
"~NMIG": 264, // automatic alias replacing hash with tilde
NMIL: 1374,
RESP: 67,
RESG: 926,
VEC0: 1465,
VEC1: 1481,
"#VEC": 1134,
"~VEC": 1134, // automatic alias replacing hash with tilde
D1x1: 827, // internal signal: interrupt handler related
"brk-done": 1382, // internal signal: interrupt handler related
INTG: 1350, // internal signal: interrupt handler related
BRtaken: 1544,
// internal state: misc pipeline state clocked by cclk (phi2)
"pipe#VEC": 1431, // latched #VEC
"pipe~VEC": 1431, // automatic alias replacing hash with tilde
"pipeT-SYNC": 537,
pipeT2out: 40,
pipeT3out: 706,
pipeT4out: 1373,
pipeT5out: 940,
pipeIPCrelated: 832,
pipeBRtaken: 832,
pipeUNK01: 1530,
pipeUNK02: 974,
pipeUNK03: 1436,
@ -664,25 +469,20 @@ pipeUNK34: 56,
pipeUNK35: 1713,
pipeUNK36: 729,
pipeUNK37: 197,
"pipe#WR.phi2": 1131,
"pipe~WR.phi2": 1131, // automatic alias replacing hash with tilde
pipeUNK38: 1131,
pipeUNK39: 151,
pipeUNK40: 456,
pipeUNK41: 1438,
pipeUNK42: 1104,
"pipe#T0": 554, // aka #T0.phi2
"pipe~T0": 554, // automatic alias replacing hash with tilde
pipeUNK43: 554,
// internal state: vector address pulldown control
pipeVectorA0: 357,
pipeVectorA1: 170,
pipeVectorA2: 45,
// internal signals: vector address pulldown control
"0/ADL0": 217,
"0/ADL1": 686,
"0/ADL2": 1193,
// internal state: datapath control drivers
pipedpc28: 683,
@ -704,170 +504,17 @@ alub5: 1678,
alub6: 235,
alub7: 1535,
// alu carry chain and decimal mode
C01: 1285,
C12: 505,
C23: 1023,
C34: 78,
C45: 142,
C56: 500,
C67: 1314,
C78: 808,
"C78.phi2": 560,
DC34: 1372, // lower nibble decimal carry
DC78: 333, // carry for decimal mode
"DC78.phi2": 164,
"#C01": 1506,
"~C01": 1506, // automatic alias replacing hash with tilde
"#C12": 1122,
"~C12": 1122, // automatic alias replacing hash with tilde
"#C23": 1003,
"~C23": 1003, // automatic alias replacing hash with tilde
"#C34": 1425,
"~C34": 1425, // automatic alias replacing hash with tilde
"#C45": 1571,
"~C45": 1571, // automatic alias replacing hash with tilde
"#C56": 427,
"~C56": 427, // automatic alias replacing hash with tilde
"#C67": 592,
"~C67": 592, // automatic alias replacing hash with tilde
"#C78": 1327,
"~C78": 1327, // automatic alias replacing hash with tilde
"DA-C01": 623,
"DA-AB2": 216,
"DA-AxB2": 516,
"DA-C45": 1144,
"#DA-ADD1": 901,
"~DA-ADD1": 901, // automatic alias replacing hash with tilde
"#DA-ADD2": 699,
"~DA-ADD2": 699, // automatic alias replacing hash with tilde
aluanorb0: 143,
aluanandb0: 1628,
aluaorb0: 693,
notaluoutmux0: 957, // alu result latch input
// misc alu internals
"#(AxBxC)0": 371,
"~(AxBxC)0": 371, // automatic alias replacing hash with tilde
"#(AxBxC)1": 965,
"~(AxBxC)1": 965, // automatic alias replacing hash with tilde
"#(AxBxC)2": 22,
"~(AxBxC)2": 22, // automatic alias replacing hash with tilde
"#(AxBxC)3": 274,
"~(AxBxC)3": 274, // automatic alias replacing hash with tilde
"#(AxBxC)4": 651,
"~(AxBxC)4": 651, // automatic alias replacing hash with tilde
"#(AxBxC)5": 486,
"~(AxBxC)5": 486, // automatic alias replacing hash with tilde
"#(AxBxC)6": 1197,
"~(AxBxC)6": 1197, // automatic alias replacing hash with tilde
"#(AxBxC)7": 532,
"~(AxBxC)7": 532, // automatic alias replacing hash with tilde
AxB1: 425,
AxB3: 640,
AxB5: 1220,
AxB7: 1241,
"#(AxB)0": 1525,
"~(AxB)0": 1525, // automatic alias replacing hash with tilde
"#(AxB)2": 701,
"~(AxB)2": 701, // automatic alias replacing hash with tilde
"#(AxB)4": 308,
"~(AxB)4": 308, // automatic alias replacing hash with tilde
"#(AxB)6": 1459,
"~(AxB)6": 1459, // automatic alias replacing hash with tilde
"(AxB)0.#C0in": 555,
"(AxB)0.~C0in": 555, // automatic alias replacing hash with tilde
"(AxB)2.#C12": 193,
"(AxB)2.~C12": 193, // automatic alias replacing hash with tilde
"(AxB)4.#C34": 65,
"(AxB)4.~C34": 65, // automatic alias replacing hash with tilde
"(AxB)6.#C56": 174,
"(AxB)6.~C56": 174, // automatic alias replacing hash with tilde
"#(AxB1).C01": 295,
"~(AxB1).C01": 295, // automatic alias replacing hash with tilde
"#(AxB3).C23": 860,
"~(AxB3).C23": 860, // automatic alias replacing hash with tilde
"#(AxB5).C45": 817,
"~(AxB5).C45": 817, // automatic alias replacing hash with tilde
"#(AxB7).C67": 1217,
"~(AxB7).C67": 1217, // automatic alias replacing hash with tilde
"#A.B0": 1628,
"~A.B0": 1628, // automatic alias replacing hash with tilde
"#A.B1": 841,
"~A.B1": 841, // automatic alias replacing hash with tilde
"#A.B2": 681,
"~A.B2": 681, // automatic alias replacing hash with tilde
"#A.B3": 350,
"~A.B3": 350, // automatic alias replacing hash with tilde
"#A.B4": 1063,
"~A.B4": 1063, // automatic alias replacing hash with tilde
"#A.B5": 477,
"~A.B5": 477, // automatic alias replacing hash with tilde
"#A.B6": 336,
"~A.B6": 336, // automatic alias replacing hash with tilde
"#A.B7": 1318,
"~A.B7": 1318, // automatic alias replacing hash with tilde
"A+B0": 693,
"A+B1": 1021,
"A+B2": 110,
"A+B3": 1313,
"A+B4": 918,
"A+B5": 1236,
"A+B6": 803,
"A+B7": 117,
"#(A+B)0": 143,
"~(A+B)0": 143, // automatic alias replacing hash with tilde
"#(A+B)1": 155,
"~(A+B)1": 155, // automatic alias replacing hash with tilde
"#(A+B)2": 1691,
"~(A+B)2": 1691, // automatic alias replacing hash with tilde
"#(A+B)3": 649,
"~(A+B)3": 649, // automatic alias replacing hash with tilde
"#(A+B)4": 404,
"~(A+B)4": 404, // automatic alias replacing hash with tilde
"#(A+B)5": 1632,
"~(A+B)5": 1632, // automatic alias replacing hash with tilde
"#(A+B)6": 1084,
"~(A+B)6": 1084, // automatic alias replacing hash with tilde
"#(A+B)7": 1398,
"~(A+B)7": 1398, // automatic alias replacing hash with tilde
"#(AxB)0": 1525,
"~(AxB)0": 1525, // automatic alias replacing hash with tilde
"#(AxB)2": 701,
"~(AxB)2": 701, // automatic alias replacing hash with tilde
"#(AxB)4": 308,
"~(AxB)4": 308, // automatic alias replacing hash with tilde
"#(AxB)6": 1459,
"~(AxB)6": 1459, // automatic alias replacing hash with tilde
"#(AxB)1": 953,
"~(AxB)1": 953, // automatic alias replacing hash with tilde
"#(AxB)3": 884,
"~(AxB)3": 884, // automatic alias replacing hash with tilde
"#(AxB)5": 1469,
"~(AxB)5": 1469, // automatic alias replacing hash with tilde
"#(AxB)7": 177,
"~(AxB)7": 177, // automatic alias replacing hash with tilde
"#aluresult0": 957, // alu result latch input
"~aluresult0": 957, // automatic alias replacing hash with tilde
"#aluresult1": 250,
"~aluresult1": 250, // automatic alias replacing hash with tilde
"#aluresult2": 740,
"~aluresult2": 740, // automatic alias replacing hash with tilde
"#aluresult3": 1071,
"~aluresult3": 1071, // automatic alias replacing hash with tilde
"#aluresult4": 296,
"~aluresult4": 296, // automatic alias replacing hash with tilde
"#aluresult5": 277,
"~aluresult5": 277, // automatic alias replacing hash with tilde
"#aluresult6": 722,
"~aluresult6": 722, // automatic alias replacing hash with tilde
"#aluresult7": 304,
"~aluresult7": 304, // automatic alias replacing hash with tilde
aluanorb1: 155,
aluanandb1: 841,
aluaorb1: 1021,
notaluoutmux1: 250, // alu result latch input
// internal signals: datapath control signals
"ADL/ABL": 639, // load ABL latches from ADL bus
"dpc-1_ADL/ABL": 639,// alias for DPControl pseudo-bus
"ADH/ABH": 821, // load ABH latches from ADH bus
"dpc-2_ADH/ABH": 821,// alias for DPControl pseudo-bus
dpc0_YSB: 801, // drive sb from y
dpc1_SBY: 325, // load y from sb
dpc2_XSB: 1263, // drive sb from x
@ -889,35 +536,21 @@ dpc16_EORS: 1666, // alu op: a xor b (?)
dpc17_SUMS: 921, // alu op: a plus b (?)
alucin: 910, // alu carry in
notalucin: 1165,
"dpc18_#DAA": 1201, // decimal related (inverted)
"dpc18_~DAA": 1201, // automatic alias replacing hash with tilde
dpc18_DAA: 1201, // decimal related
dpc19_ADDSB7: 214, // alu to sb bit 7 only
dpc20_ADDSB06: 129, // alu to sb bits 6-0 only
dpc21_ADDADL: 1015, // alu to adl
alurawcout: 808, // alu raw carry out (no decimal adjust)
notalucout: 412, // alu carry out (inverted)
alucout: 1146, // alu carry out (latched by phi2)
"#alucout": 206,
"~alucout": 206, // automatic alias replacing hash with tilde
"##alucout": 465,
"~~alucout": 465, // automatic alias replacing hash with tilde
notaluvout: 1308, // alu overflow out
aluvout: 938, // alu overflow out (latched by phi2)
"#DBZ": 1268, // internal signal: not (databus is zero)
"~DBZ": 1268, // automatic alias replacing hash with tilde
DBZ: 744, // internal signal: databus is zero
DBNeg: 1200, // internal signal: databus is negative (top bit of db) aka P-#DB7in
DBNeg: 1200, // automatic alias replacing hash with tilde
"dpc22_#DSA": 725, // decimal related/SBC only (inverted)
"dpc22_~DSA": 725, // automatic alias replacing hash with tilde
dpc22_DSA: 725, // decimal related/SBC only
dpc23_SBAC: 534, // (optionalls decimal-adjusted) sb to acc
dpc24_ACSB: 1698, // acc to sb
dpc25_SBDB: 1060, // sb pass-connects to idb (bi-directionally)
dpc25_SBDB: 1060, // sb pass-connects to idb
dpc26_ACDB: 1331, // acc to idb
dpc27_SBADH: 140, // sb pass-connects to adh (bi-directionally)
dpc27_SBADH: 140, // sb pass-connects to adh
dpc28_0ADH0: 229, // zero to adh0 bit0 only
dpc29_0ADH17: 203, // zero to adh bits 7-1 only
@ -926,24 +559,14 @@ dpc31_PCHPCH: 741, // load pch from pch incremented
dpc32_PCHADH: 1235, // drive adh from pch incremented
dpc33_PCHDB: 247, // drive idb from pch incremented
dpc34_PCLC: 1704, // pch carry in and pcl FF detect?
dpc35_PCHC: 1334, // pch 0x?F detect - half-carry
"dpc36_#IPC": 379, // pcl carry in (inverted)
"dpc36_~IPC": 379, // automatic alias replacing hash with tilde
dpc35: 1334, // pcl 0x?F detect - half-carry
dpc36_IPC: 379, // pcl carry in
dpc37_PCLDB: 283, // drive idb from pcl incremented
dpc38_PCLADL: 438, // drive adl from pcl incremented
dpc39_PCLPCL: 898, // load pcl from pcl incremented
dpc40_ADLPCL: 414, // load pcl from adl
"dpc41_DL/ADL": 1564,// pass-connect adl to mux node driven by idl
"dpc42_DL/ADH": 41, // pass-connect adh to mux node driven by idl
"dpc43_DL/DB": 863, // pass-connect idb to mux node driven by idl
dpc41: 1564, // pass-connect adl to mux node driven by idl
dpc42: 41, // pass-connect adh to mux node driven by idl
dpc43: 863, // pass-connect idb to mux node driven by idl
}
/* many bus names taken from Donald F. Hanson's block diagram, found
* http://www.weihenstephan.org/~michaste/pagetable/6502/6502.jpg
* from his paper "A VHDL conversion tool for logic equations with embedded D latches"
* http://portal.acm.org/citation.cfm?id=1275143.1275151
* also available at
* http://www.ncsu.edu/wcae/WCAE1/hanson.pdf
*/

View File

@ -1,36 +0,0 @@
// This file testprogram.js can be substituted by one of several tests
// which may not be redistributable
// for example
// cbmbasic loaded at 0xa000 with entry point 0xe394
// test6502 (by Bird Computer) loaded at 0x8000 with entry point 0x8000
//
// (can use xxd -i to convert binary into C include syntax, as a starting point)
//
testprogramAddress=0x0000;
// we want to auto-clear the console if any output is sent by the program
var consoleboxStream="";
// demonstrate write hook
writeTriggers[0x000F]="consoleboxStream += String.fromCharCode(d);"+
"consolebox.innerHTML = consoleboxStream;";
// demonstrate read hook (not used by this test program)
readTriggers[0xD011]="((consolegetc==undefined)?0:0xff)"; // return zero until we have a char
readTriggers[0xD010]="var c=consolegetc; consolegetc=undefined; (c)";
testprogram = [
0xa9, 0x00, // LDA #$00
0x20, 0x10, 0x00, // JSR $0010
0x4c, 0x02, 0x00, // JMP $0002
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x40,
0xe8, // INX
0x88, // DEY
0xe6, 0x0F, // INC $0F
0x38, // SEC
0x69, 0x02, // ADC #$02
0x60 // RTS
];

File diff suppressed because it is too large Load Diff

View File

@ -89,6 +89,6 @@ table.memtable {
}
#title {
font-size:30px;
font-size:30px;
font-weight:bold;
}

276
wires.js
View File

@ -21,15 +21,80 @@
*/
var frame, chipbg, overlay, hilite, hitbuffer, ctx;
var centerx=300, centery=300;
var zoom=1;
var dragMouseX, dragMouseY, moved;
var statbox;
// Some constants for the graphics presentation
// the canvas is embedded in an 800x600 clipping div
// which gives rise to some of the 300 and 400 values in the code
// there are also some 600 values
// the 6502D chip coords are in the box (216,179) to (8983,9807)
// we have 4 canvases all the same size, now 2000 pixels square
// chip background - the layout
// overlay - a red/white transparency to show logic high or low
// hilite - to show the selected polygon
// hitbuffer - abusing color values to return which polygon is under a point
// we no longer use a scaling transform - we now scale the chip data at
// the point of drawing line segments
// if the canvas is any smaller than chip coordinates there will be
// rounding artifacts, and at high zoom there will be anti-aliasing on edges.
var grMaxZoom=12;
var grChipSize=10000;
var grCanvasSize=2000;
var grLineWidth=1;
// Index of layerNames corresponds to index into drawLayers
var layernames = ['metal', 'switched diffusion', 'inputdiode', 'grounded diffusion', 'powered diffusion', 'polysilicon'];
var colors = ['rgba(128,128,192,0.4)','#FFFF00','#FF00FF','#4DFF4D',
'#FF4D4D','#801AC0','rgba(128,0,255,0.75)'];
var drawlayers = [true, true, true, true, true, true];
var nodes = new Array();
var transistors = {};
var nodenamelist=[];
var ngnd = nodenames['vss'];
var npwr = nodenames['vcc'];
var chipLayoutIsVisible = true; // only modified in expert mode
var hilited = [];
/////////////////////////
//
// Drawing Setup
//
/////////////////////////
// try to present a meaningful page before starting expensive work
function setup(){
statbox = document.getElementById('status');
setStatus('loading 6502...');
setTimeout(setup_part2, 0);
}
function setup_part2(){
frame = document.getElementById('frame');
statbox = document.getElementById('status');
setupNodes();
setupTransistors();
setupLayerVisibility();
setupBackground();
setupOverlay();
setupHilite();
setupHitBuffer();
recenter();
refresh();
setupTable();
window.onkeypress = function(e){handleKey(e);}
hilite.onmousedown = function(e){mouseDown(e);}
setStatus('resetting 6502...');
setTimeout(setup_part3, 0);
}
function setup_part3(){
initChip();
document.getElementById('stop').style.visibility = 'hidden';
go();
}
function setupNodes(){
for(var i in segdefs){
@ -37,7 +102,7 @@ function setupNodes(){
var w = seg[0];
if(nodes[w]==undefined)
nodes[w] = {segs: new Array(), num: w, pullup: seg[1]=='+',
state: false, gates: new Array(), c1c2s: new Array()};
state: 'fl', gates: new Array(), c1c2s: new Array()};
if(w==ngnd) continue;
if(w==npwr) continue;
nodes[w].segs.push(seg.slice(3));
@ -51,13 +116,10 @@ function setupTransistors(){
var gate = tdef[1];
var c1 = tdef[2];
var c2 = tdef[3];
var bb = tdef[4];
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);
var trans = {name: name, on: false, gate: gate, c1: c1, c2: c2};
nodes[gate].gates.push(name);
nodes[c1].c1c2s.push(name);
nodes[c2].c1c2s.push(name);
transistors[name] = trans;
}
}
@ -136,12 +198,10 @@ function hexdigit(n){return '0123456789ABCDEF'.charAt(n);}
/////////////////////////
function refresh(){
if(!chipLayoutIsVisible) return;
ctx.clearRect(0,0,grCanvasSize,grCanvasSize);
ctx.clearRect(0,0,grCanvasSize,grCanvasSize);
for(i in nodes){
if(isNodeHigh(i)) overlayNode(nodes[i].segs);
}
hiliteNode(hilited);
}
function overlayNode(w){
@ -152,85 +212,110 @@ function overlayNode(w){
}
}
// originally to highlight using a list of node numbers
// but can now include transistor names
function hiliteNode(n){
var ctx = hilite.getContext('2d');
ctx.clearRect(0,0,grCanvasSize,grCanvasSize);
ctx.fillStyle = 'rgba(255,255,255,0.7)';
if(n==-1) return;
hilited = n;
if(isNodeHigh(n[0]))
ctx.fillStyle = 'rgba(255,0,0,0.7)';
for(var i in n){
if(typeof n[i] != "number") {
hiliteTrans([n[i]]);
continue;
}
if(isNodeHigh(n[i])) {
ctx.fillStyle = 'rgba(255,0,0,0.7)';
} else {
ctx.fillStyle = 'rgba(255,255,255,0.7)';
}
var segs = nodes[n[i]].segs;
for(var s in segs){drawSeg(ctx, segs[s]); ctx.fill();}
}
}
// highlight a single transistor (additively - does not clear highlighting)
function hiliteTrans(n){
var ctx = hilite.getContext('2d');
ctx.strokeStyle = 'rgba(255,255,255,0.7)';
ctx.lineWidth = 4
for(var t in n){
var bb = transistors[n[t]].bb
var segs = [[bb[0], bb[2], bb[1], bb[2], bb[1], bb[3], bb[0], bb[3]]]
for(var s in segs){drawSeg(ctx, segs[s]); ctx.stroke();}
}
}
function ctxDrawBox(ctx, xMin, yMin, xMax, yMax){
var cap=ctx.lineCap;
ctx.lineCap="square";
ctx.beginPath();
ctx.moveTo(xMin, yMin);
ctx.lineTo(xMin, yMax);
ctx.lineTo(xMax, yMax);
ctx.lineTo(xMax, yMin);
ctx.lineTo(xMin, yMin);
ctx.stroke();
ctx.lineCap=cap;
}
// takes a bounding box in chip coords and centres the display over it
function zoomToBox(xmin,xmax,ymin,ymax){
var xmid=(xmin+xmax)/2;
var ymid=(ymin+ymax)/2;
var x=(xmid+grChipOffsetX)/grChipSize*600;
var y=600-(ymid-grChipOffsetY)/grChipSize*600;
// Zoom to fill 80% of the window with the selection
var fillfactor=0.80;
var dx=xmax-xmin;
var dy=ymax-ymin;
if (dx < 1) dx=1;
if (dy < 1) dy=1;
var zx=(800/600)*fillfactor*grChipSize/dx;
var zy=fillfactor*grChipSize/dy;
var zoom=Math.min(zx,zy);
if (zoom < 1) {
zoom = 1;
}
if (zoom > grMaxZoom) {
zoom = grMaxZoom;
}
moveHere([x,y,zoom]);
}
function drawSeg(ctx, seg){
var dx = grChipOffsetX;
var dy = grChipOffsetY;
if(noGraphics) return;
var dx = 400;
ctx.beginPath();
ctx.moveTo(grScale(seg[0]+dx), grScale(grChipSize-seg[1]+dy));
for(var i=2;i<seg.length;i+=2) ctx.lineTo(grScale(seg[i]+dx), grScale(grChipSize-seg[i+1]+dy));
ctx.lineTo(grScale(seg[0]+dx), grScale(grChipSize-seg[1]+dy));
ctx.moveTo(grScale(seg[0]+dx), grScale(grChipSize-seg[1]));
for(var i=2;i<seg.length;i+=2) ctx.lineTo(grScale(seg[i]+dx), grScale(grChipSize-seg[i+1]));
ctx.lineTo(grScale(seg[0]+dx), grScale(grChipSize-seg[1]));
}
/////////////////////////
//
// User Interface
//
/////////////////////////
function handleKey(e){
var c = e.charCode;
c = String.fromCharCode(c);
if('<>?np'.indexOf(c)==-1) return;
if(c=='<' && zoom>1) setZoom(zoom/1.2);
else if(c=='>' && zoom<grMaxZoom) setZoom(zoom*1.2);
else if(c=='?') setZoom(1);
else if(c=='n') stepForward();
else if(c=='p') stepBack();
}
function mouseDown(e){
e.preventDefault();
moved=false;
dragMouseX = e.clientX;
dragMouseY = e.clientY;
window.onmousemove = function(e){mouseMove(e)};
window.onmouseup = function(e){mouseUp(e)};
}
function mouseMove(e){
moved = true;
if(zoom==1) return;
var dx = e.clientX-dragMouseX;
var dy = e.clientY-dragMouseY;
dragMouseX = e.clientX;
dragMouseY = e.clientY;
centerx-=dx/zoom;
centerx = Math.max(centerx, 400/zoom);
centerx = Math.min(centerx, 600-400/zoom);
centery-=dy/zoom;
centery = Math.max(centery, 300/zoom);
centery = Math.min(centery, 600-300/zoom);
recenter();
}
function mouseUp(e){
if(!moved) handleClick(e);
window.onmousemove = undefined;
window.onmouseup = undefined;
}
function setZoom(n){
zoom = n;
setChipStyle({
width: 600*n+'px',
height: 600*n+'px'
});
recenter();
}
function recenter(){
var top = -centery*zoom+300;
top = Math.min(top, 0);
top = Math.max(top, -600*(zoom-1));
var left = -centerx*zoom+400;
left = Math.min(left, 0);
left = Math.max(left, (zoom==1)?100:-600*zoom+800);
setChipStyle({
top: top+'px',
left: left+'px',
});
}
function handleClick(e){
var x = localx(hilite, e.clientX)/zoom;
var y = localy(hilite, e.clientY)/zoom;
var w = findNodeNumber(x,y);
if(e.shiftKey) hiliteNode(getNodeGroup(w));
else {var a=new Array(); a.push(w); hiliteNode(a);}
var cx = Math.round(x*grChipSize/600);
var cy = Math.round(y*grChipSize/600);
if(w==-1) setStatus('x:',cx,'<br>','y:',cy);
else {setStatus('x:',cx, 'y:', cy,'<br>','node:',w, nodeName(w));}
}
function findNodeNumber(x,y){
@ -243,17 +328,26 @@ function findNodeNumber(x,y){
return (high<<8)+(mid<<4)+low;
}
function clearHighlight(){
// remove red/white overlay according to logic value
// for easier layout navigation
ctx.clearRect(0,0,grCanvasSize,grCanvasSize);
}
function updateShow(layer, on){
drawlayers[layer]=on;
setupBackground();
}
/////////////////////////
//
// Etc.
//
/////////////////////////
function setChipStyle(props){
for(var i in props){
chipbg.style[i] = props[i];
overlay.style[i] = props[i];
hilite.style[i] = props[i];
hitbuffer.style[i] = props[i];
}
}
// we draw the chip data scaled down to the canvas
// and so avoid scaling a large canvas
function grScale(x){
@ -270,20 +364,10 @@ function localy(el, gy){
function setStatus(){
var res = '';
// pad the arguments to make this a three-line display
// there must be a clean way to do this
if(arguments[1]==undefined)arguments[1]="";
if(arguments[2]==undefined)arguments[2]="";
arguments.length=3;
for(var i=0;i<arguments.length;i++) res=res+arguments[i]+'<br>';
for(var i=0;i<arguments.length;i++) res=res+arguments[i]+' ';
statbox.innerHTML = res;
}
function setupNodeNameList(){
for(var i in nodenames)
nodenamelist.push(i);
}
function nodeName(n) {
for(var i in nodenames){
if(nodenames[i]==n) return i;