mirror of
https://github.com/mist64/perfect6502.git
synced 2024-06-09 03:29:27 +00:00
Merge 054bcf51d0
into 268d16647c
This commit is contained in:
commit
3d227038ff
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -1,3 +1,5 @@
|
|||
build
|
||||
*.xcodeproj
|
||||
# emacs-style backup files
|
||||
*~
|
||||
# patch detritus
|
||||
|
@ -6,3 +8,4 @@
|
|||
# object files
|
||||
cbmbasic
|
||||
*.o
|
||||
|
||||
|
|
2
Makefile
2
Makefile
|
@ -1,6 +1,6 @@
|
|||
OBJS=perfect6502.o netlist_sim.o
|
||||
OBJS+=cbmbasic/cbmbasic.o cbmbasic/runtime.o cbmbasic/runtime_init.o cbmbasic/plugin.o cbmbasic/console.o cbmbasic/emu.o
|
||||
OBJS+=measure.o
|
||||
#OBJS+=measure.o
|
||||
CFLAGS=-Werror -Wall -O3
|
||||
CC=cc
|
||||
|
||||
|
|
|
@ -1,17 +1,37 @@
|
|||
#include <stdio.h>
|
||||
#include "../perfect6502.h"
|
||||
#include "runtime.h"
|
||||
#include "runtime_init.h"
|
||||
#include <time.h>
|
||||
|
||||
|
||||
/*
|
||||
See https://www.c64-wiki.com/wiki/C64-Commands
|
||||
|
||||
10 PRINT 200 * 25.4
|
||||
20 PRINT 200 / 3.3333
|
||||
30 END
|
||||
RUN
|
||||
|
||||
*/
|
||||
|
||||
#define SHOW_AVG_SPEED 0
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
int clk = 0;
|
||||
|
||||
|
||||
void *state = initAndResetChip();
|
||||
|
||||
/* set up memory for user program */
|
||||
init_monitor();
|
||||
|
||||
#if SHOW_AVG_SPEED
|
||||
clock_t end_time;
|
||||
clock_t start_time = clock();
|
||||
#endif
|
||||
|
||||
/* emulate the 6502! */
|
||||
for (;;) {
|
||||
step(state);
|
||||
|
@ -19,7 +39,18 @@ main()
|
|||
if (clk)
|
||||
handle_monitor(state);
|
||||
|
||||
// chipStatus(state);
|
||||
//if (!(cycle % 1000)) printf("%d\n", cycle);
|
||||
};
|
||||
/* chipStatus(state);
|
||||
*/
|
||||
|
||||
#if SHOW_AVG_SPEED
|
||||
if ( (cycle % 20000) == 0 ) {
|
||||
end_time = clock();
|
||||
double time = (end_time - start_time)/ (double)(CLOCKS_PER_SEC);
|
||||
double speed = cycle / time;
|
||||
printf("cycle %lu, speed %g steps per second\n", cycle, speed);
|
||||
}
|
||||
#endif
|
||||
|
||||
} /* end infinite loop */
|
||||
|
||||
}
|
||||
|
|
|
@ -20,11 +20,11 @@ enum {
|
|||
COLOR_GREY3,
|
||||
};
|
||||
|
||||
void clear_screen();
|
||||
void up_cursor();
|
||||
void down_cursor();
|
||||
void left_cursor();
|
||||
void right_cursor();
|
||||
void clear_screen(void);
|
||||
void up_cursor(void);
|
||||
void down_cursor(void);
|
||||
void left_cursor(void);
|
||||
void right_cursor(void);
|
||||
void move_cursor(int x, int y);
|
||||
void get_cursor(int* x, int* y);
|
||||
void set_color(int c);
|
||||
|
|
|
@ -16,7 +16,7 @@ static uint16_t PC;
|
|||
static uint8_t A, X, Y, S, P;
|
||||
static uint8_t temp_lo, temp_hi;
|
||||
|
||||
#define TEMP16 (temp_lo | temp_hi << 8)
|
||||
#define TEMP16 (uint16_t)( ((uint16_t)temp_lo) | ((uint16_t)temp_hi) << 8)
|
||||
|
||||
static uint16_t AB;
|
||||
static uint8_t DB;
|
||||
|
@ -49,7 +49,7 @@ LOAD(uint16_t a)
|
|||
#define IS_T7 (t & T7)
|
||||
|
||||
void
|
||||
IFETCH()
|
||||
IFETCH(void)
|
||||
{
|
||||
AB = PC;
|
||||
RW = RW_READ;
|
||||
|
@ -57,7 +57,7 @@ IFETCH()
|
|||
}
|
||||
|
||||
void
|
||||
init()
|
||||
init(void)
|
||||
{
|
||||
t = T1;
|
||||
ir = 0;
|
||||
|
@ -71,7 +71,7 @@ init()
|
|||
}
|
||||
|
||||
void
|
||||
EOI_INCPC_READPC()
|
||||
EOI_INCPC_READPC(void)
|
||||
{
|
||||
PC++;
|
||||
t <<= 1;
|
||||
|
@ -80,31 +80,31 @@ EOI_INCPC_READPC()
|
|||
}
|
||||
|
||||
void
|
||||
DB_TO_ADDRLO()
|
||||
DB_TO_ADDRLO(void)
|
||||
{
|
||||
temp_lo = DB;
|
||||
}
|
||||
void
|
||||
DB_TO_ADDRHI()
|
||||
DB_TO_ADDRHI(void)
|
||||
{
|
||||
temp_hi = DB;
|
||||
}
|
||||
|
||||
void
|
||||
EOI()
|
||||
EOI(void)
|
||||
{
|
||||
t <<= 1;
|
||||
}
|
||||
|
||||
void
|
||||
EOI_INCPC()
|
||||
EOI_INCPC(void)
|
||||
{
|
||||
PC++;
|
||||
EOI();
|
||||
}
|
||||
|
||||
void
|
||||
EOI_INCPC_READADDR()
|
||||
EOI_INCPC_READADDR(void)
|
||||
{
|
||||
EOI_INCPC();
|
||||
AB = TEMP16;
|
||||
|
@ -112,7 +112,7 @@ EOI_INCPC_READADDR()
|
|||
}
|
||||
|
||||
void
|
||||
EOI_INCPC_WRITEADDR()
|
||||
EOI_INCPC_WRITEADDR(void)
|
||||
{
|
||||
EOI_INCPC();
|
||||
AB = TEMP16;
|
||||
|
@ -120,7 +120,7 @@ EOI_INCPC_WRITEADDR()
|
|||
}
|
||||
|
||||
void
|
||||
pha()
|
||||
pha(void)
|
||||
{
|
||||
printf("%s",__func__);
|
||||
if (IS_T2) {
|
||||
|
@ -138,7 +138,7 @@ pha()
|
|||
}
|
||||
|
||||
void
|
||||
plp()
|
||||
plp(void)
|
||||
{
|
||||
printf("%s",__func__);
|
||||
if (IS_T2) {
|
||||
|
@ -162,7 +162,7 @@ plp()
|
|||
}
|
||||
|
||||
void
|
||||
txs()
|
||||
txs(void)
|
||||
{
|
||||
printf("%s",__func__);
|
||||
/* T2 */
|
||||
|
@ -171,7 +171,7 @@ txs()
|
|||
}
|
||||
|
||||
void
|
||||
lda_imm()
|
||||
lda_imm(void)
|
||||
{
|
||||
printf("%s",__func__);
|
||||
/* T2 */
|
||||
|
@ -181,7 +181,7 @@ lda_imm()
|
|||
}
|
||||
|
||||
void
|
||||
ldx_imm()
|
||||
ldx_imm(void)
|
||||
{
|
||||
printf("%s",__func__);
|
||||
/* T2 */
|
||||
|
@ -191,7 +191,7 @@ ldx_imm()
|
|||
}
|
||||
|
||||
void
|
||||
ldy_imm()
|
||||
ldy_imm(void)
|
||||
{
|
||||
printf("%s",__func__);
|
||||
/* T2 */
|
||||
|
@ -201,7 +201,7 @@ ldy_imm()
|
|||
}
|
||||
|
||||
void
|
||||
lda_abs()
|
||||
lda_abs(void)
|
||||
{
|
||||
printf("%s",__func__);
|
||||
if (IS_T2) {
|
||||
|
@ -217,7 +217,7 @@ lda_abs()
|
|||
}
|
||||
|
||||
void
|
||||
sta_abs()
|
||||
sta_abs(void)
|
||||
{
|
||||
printf("%s",__func__);
|
||||
if (IS_T2) {
|
||||
|
@ -235,7 +235,7 @@ sta_abs()
|
|||
static int cycle = 0;
|
||||
|
||||
void
|
||||
emulate_step()
|
||||
emulate_step(void)
|
||||
{
|
||||
/* memory */
|
||||
if (RW == RW_READ) {
|
||||
|
@ -284,22 +284,22 @@ emulate_step()
|
|||
}
|
||||
|
||||
void
|
||||
setup_emu()
|
||||
setup_emu(void)
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
void
|
||||
reset_emu()
|
||||
reset_emu(void)
|
||||
{
|
||||
init();
|
||||
PC = memory[0xFFFC] | memory[0xFFFD] << 8;
|
||||
PC = (uint16_t)( memory[0xFFFC] | (((uint16_t)memory[0xFFFD]) << 8) );
|
||||
printf("PC %x\n", PC);
|
||||
IFETCH();
|
||||
}
|
||||
|
||||
int
|
||||
emu_measure_instruction()
|
||||
emu_measure_instruction(void)
|
||||
{
|
||||
|
||||
for (;;) {
|
||||
|
|
|
@ -55,8 +55,9 @@
|
|||
#include "console.h"
|
||||
|
||||
static unsigned short
|
||||
get_chrptr() {
|
||||
return RAM[0x7A] | RAM[0x7B]<<8;
|
||||
get_chrptr(void) {
|
||||
return (unsigned short)(((unsigned short)RAM[0x7A])
|
||||
| (((unsigned short)RAM[0x7B])<<8));
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -97,19 +98,19 @@ call(unsigned short pc) {
|
|||
}
|
||||
|
||||
static void
|
||||
check_comma() {
|
||||
check_comma(void) {
|
||||
call(0xAEFD);
|
||||
}
|
||||
|
||||
static unsigned short
|
||||
get_word() {
|
||||
get_word(void) {
|
||||
call(0xAD8A);
|
||||
call(0xB7F7);
|
||||
return RAM[0x14] | (RAM[0x15]<<8);
|
||||
return (unsigned short)(((unsigned short)RAM[0x14]) | (((unsigned short)RAM[0x15])<<8));
|
||||
}
|
||||
|
||||
static unsigned char
|
||||
get_byte() {
|
||||
get_byte(void) {
|
||||
call(0xB79E);
|
||||
return X;
|
||||
}
|
||||
|
@ -120,8 +121,10 @@ get_string(char *s) {
|
|||
|
||||
call(0xAD9E);
|
||||
call(0xB6A3);
|
||||
for (i = 0; i < A; i++)
|
||||
s[i] = RAM[(X|(Y<<8))+i];
|
||||
unsigned short addr = (unsigned short) ( ((unsigned short)X) | (((unsigned short)Y)<<8) );
|
||||
for (i = 0; i < A; i++) {
|
||||
s[i] = (char)RAM[addr+i];
|
||||
}
|
||||
s[A] = 0;
|
||||
}
|
||||
|
||||
|
@ -169,7 +172,7 @@ error(unsigned char index) {
|
|||
* print friendlier strings, or implement "ON ERROR GOTO".
|
||||
*/
|
||||
unsigned short
|
||||
plugin_error() {
|
||||
plugin_error(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -179,7 +182,7 @@ plugin_error() {
|
|||
* This gets called whenever we are in direct mode.
|
||||
*/
|
||||
unsigned short
|
||||
plugin_main() {
|
||||
plugin_main(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -187,7 +190,7 @@ plugin_main() {
|
|||
* Tokenize BASIC Text
|
||||
*/
|
||||
unsigned short
|
||||
plugin_crnch() {
|
||||
plugin_crnch(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -195,7 +198,7 @@ plugin_crnch() {
|
|||
* BASIC Text LIST
|
||||
*/
|
||||
unsigned short
|
||||
plugin_qplop() {
|
||||
plugin_qplop(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -205,7 +208,7 @@ plugin_qplop() {
|
|||
* This is used for interpreting statements.
|
||||
*/
|
||||
unsigned short
|
||||
plugin_gone() {
|
||||
plugin_gone(void) {
|
||||
set_chrptr(get_chrptr()+1);
|
||||
for (;;) {
|
||||
unsigned short chrptr;
|
||||
|
@ -282,6 +285,6 @@ plugin_gone() {
|
|||
* New functions and operators go here.
|
||||
*/
|
||||
unsigned short
|
||||
plugin_eval() {
|
||||
plugin_eval(void) {
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <windows.h> // FindFirstFile, FindNextFile
|
||||
//#include <windows.h> // FindFirstFile, FindNextFile
|
||||
#include "readdir.h"
|
||||
|
||||
typedef struct dir_private
|
||||
|
|
|
@ -162,7 +162,7 @@ init_os(int argc, char **argv) {
|
|||
if (fgetc(input_file)=='#') {
|
||||
char c;
|
||||
do {
|
||||
c = fgetc(input_file);
|
||||
c = (char) fgetc(input_file);
|
||||
} while((c!=13)&&(c!=10));
|
||||
} else {
|
||||
fseek(input_file, 0, SEEK_SET);
|
||||
|
@ -182,13 +182,13 @@ int plugin = 0;
|
|||
|
||||
void
|
||||
replace_vector(unsigned short address, unsigned short new, unsigned short *old) {
|
||||
*old = RAM[address] | (RAM[address+1]<<8);
|
||||
*old = (unsigned short)( (unsigned short)RAM[address] | (((unsigned short)RAM[address+1])<<8) );
|
||||
RAM[address] = (new)&0xFF;
|
||||
RAM[address+1] = (new)>>8;
|
||||
}
|
||||
|
||||
void
|
||||
plugin_on() {
|
||||
plugin_on(void) {
|
||||
if (plugin)
|
||||
return;
|
||||
|
||||
|
@ -203,7 +203,7 @@ plugin_on() {
|
|||
}
|
||||
|
||||
static void
|
||||
plugin_off() {
|
||||
plugin_off(void) {
|
||||
unsigned short dummy;
|
||||
|
||||
if (!plugin)
|
||||
|
@ -220,13 +220,13 @@ plugin_off() {
|
|||
}
|
||||
|
||||
static void
|
||||
SETMSG() {
|
||||
SETMSG(void) {
|
||||
kernal_msgflag = A;
|
||||
A = kernal_status;
|
||||
}
|
||||
|
||||
static void
|
||||
MEMTOP() {
|
||||
MEMTOP(void) {
|
||||
#if DEBUG /* CBMBASIC doesn't do this */
|
||||
if (!C) {
|
||||
printf("UNIMPL: set top of RAM");
|
||||
|
@ -245,7 +245,7 @@ MEMTOP() {
|
|||
|
||||
/* MEMBOT */
|
||||
static void
|
||||
MEMBOT() {
|
||||
MEMBOT(void) {
|
||||
#if DEBUG /* CBMBASIC doesn't do this */
|
||||
if (!C) {
|
||||
printf("UNIMPL: set bot of RAM");
|
||||
|
@ -258,13 +258,13 @@ MEMBOT() {
|
|||
|
||||
/* READST */
|
||||
static void
|
||||
READST() {
|
||||
READST(void) {
|
||||
A = kernal_status;
|
||||
}
|
||||
|
||||
/* SETLFS */
|
||||
static void
|
||||
SETLFS() {
|
||||
SETLFS(void) {
|
||||
kernal_lfn = A;
|
||||
kernal_dev = X;
|
||||
kernal_sec = Y;
|
||||
|
@ -272,14 +272,14 @@ SETLFS() {
|
|||
|
||||
/* SETNAM */
|
||||
static void
|
||||
SETNAM() {
|
||||
kernal_filename = X | Y<<8;
|
||||
SETNAM(void) {
|
||||
kernal_filename = (unsigned short)( ((unsigned short)X) | (((unsigned short)Y)<<8) );
|
||||
kernal_filename_len = A;
|
||||
}
|
||||
|
||||
/* OPEN */
|
||||
static void
|
||||
OPEN() {
|
||||
OPEN(void) {
|
||||
kernal_status = 0;
|
||||
if (kernal_files[kernal_lfn]) {
|
||||
C = 1;
|
||||
|
@ -305,7 +305,7 @@ OPEN() {
|
|||
|
||||
/* CLOSE */
|
||||
static void
|
||||
CLOSE() {
|
||||
CLOSE(void) {
|
||||
if (!kernal_files[kernal_lfn]) {
|
||||
C = 1;
|
||||
A = KERN_ERR_FILE_NOT_OPEN;
|
||||
|
@ -318,7 +318,7 @@ CLOSE() {
|
|||
|
||||
/* CHKIN */
|
||||
static void
|
||||
CHKIN() {
|
||||
CHKIN(void) {
|
||||
kernal_status = 0;
|
||||
if (!kernal_files[X]) {
|
||||
C = 1;
|
||||
|
@ -332,7 +332,7 @@ CHKIN() {
|
|||
|
||||
/* CHKOUT */
|
||||
static void
|
||||
CHKOUT() {
|
||||
CHKOUT(void) {
|
||||
kernal_status = 0;
|
||||
if (!kernal_files[X]) {
|
||||
C = 1;
|
||||
|
@ -346,7 +346,7 @@ CHKOUT() {
|
|||
|
||||
/* CLRCHN */
|
||||
static void
|
||||
CLRCHN() {
|
||||
CLRCHN(void) {
|
||||
kernal_input = 0;
|
||||
kernal_output = 0;
|
||||
}
|
||||
|
@ -358,7 +358,7 @@ int fakerun_index = 0;
|
|||
|
||||
/* CHRIN */
|
||||
static void
|
||||
CHRIN() {
|
||||
CHRIN(void) {
|
||||
if ((!interactive) && (readycount==2)) {
|
||||
exit(0);
|
||||
}
|
||||
|
@ -370,25 +370,25 @@ CHRIN() {
|
|||
} else {
|
||||
if (kernal_files_next[kernal_input] == EOF)
|
||||
kernal_files_next[kernal_input] = fgetc(kernal_files[kernal_input]);
|
||||
A = kernal_files_next[kernal_input];
|
||||
A = (unsigned char) kernal_files_next[kernal_input];
|
||||
kernal_files_next[kernal_input] = fgetc(kernal_files[kernal_input]);
|
||||
if (kernal_files_next[kernal_input] == EOF)
|
||||
kernal_status |= KERN_ST_EOF;
|
||||
}
|
||||
} else if (!input_file) {
|
||||
A = getchar(); /* stdin */
|
||||
A = (unsigned char) getchar(); /* stdin */
|
||||
if (A=='\n') A = '\r';
|
||||
} else {
|
||||
if (fakerun) {
|
||||
A = run[fakerun_index++];
|
||||
A = (unsigned char) run[fakerun_index++];
|
||||
if (fakerun_index==sizeof(run))
|
||||
input_file = 0; /* switch to stdin */
|
||||
} else {
|
||||
A = fgetc(input_file);
|
||||
A = (unsigned char) fgetc(input_file);
|
||||
if ((A==255)&&(readycount==1)) {
|
||||
fakerun = 1;
|
||||
fakerun_index = 0;
|
||||
A = run[fakerun_index++];
|
||||
A = (unsigned char) run[fakerun_index++];
|
||||
}
|
||||
if (A=='\n') A = '\r';
|
||||
}
|
||||
|
@ -398,7 +398,7 @@ CHRIN() {
|
|||
|
||||
/* CHROUT */
|
||||
static void
|
||||
CHROUT() {
|
||||
CHROUT(void) {
|
||||
//return;
|
||||
//exit(1);
|
||||
#if 0
|
||||
|
@ -550,7 +550,7 @@ printf("CHROUT: %d @ %x,%x,%x,%x\n", A, a, b, c, d);
|
|||
|
||||
/* LOAD */
|
||||
static void
|
||||
LOAD() {
|
||||
LOAD(void) {
|
||||
FILE *f;
|
||||
struct stat st;
|
||||
unsigned short start;
|
||||
|
@ -599,13 +599,13 @@ LOAD() {
|
|||
while ((dp = readdir(dirp))) {
|
||||
size_t namlen = strlen(dp->d_name);
|
||||
stat(dp->d_name, &st);
|
||||
file_size = (st.st_size + 253)/254; /* convert file size from num of bytes to num of blocks(254 bytes) */
|
||||
file_size = (int) ((st.st_size + 253)/254); /* convert file size from num of bytes to num of blocks(254 bytes) */
|
||||
if (file_size>0xFFFF)
|
||||
file_size = 0xFFFF;
|
||||
old_memp = memp;
|
||||
memp += 2;
|
||||
RAM[memp++] = file_size & 0xFF;
|
||||
RAM[memp++] = file_size >> 8;
|
||||
RAM[memp++] = (unsigned char)(file_size & 0xFF);
|
||||
RAM[memp++] = (unsigned char)(file_size >> 8);
|
||||
if (file_size<1000) {
|
||||
RAM[memp++] = ' ';
|
||||
if (file_size<100) {
|
||||
|
@ -621,7 +621,7 @@ LOAD() {
|
|||
memcpy(&RAM[memp], dp->d_name, namlen);
|
||||
memp += namlen;
|
||||
RAM[memp++] = '"';
|
||||
for (i=namlen; i<16; i++)
|
||||
for (i=(int)namlen; i<16; i++)
|
||||
RAM[memp++] = ' ';
|
||||
RAM[memp++] = ' ';
|
||||
RAM[memp++] = 'P';
|
||||
|
@ -667,10 +667,10 @@ for (i=0; i<255; i++) {
|
|||
f = fopen((char*)&RAM[kernal_filename], "rb");
|
||||
if (!f)
|
||||
goto file_not_found;
|
||||
start = ((unsigned char)fgetc(f)) | ((unsigned char)fgetc(f))<<8;
|
||||
start = (unsigned short)( (unsigned char)fgetc(f) | (((unsigned short)fgetc(f))<<8) );
|
||||
if (!kernal_sec)
|
||||
start = X | Y<<8;
|
||||
end = start + fread(&RAM[start], 1, 65536-start, f); /* TODO may overwrite ROM */
|
||||
start = (unsigned short)(X | (((unsigned short)Y)<<8) );
|
||||
end = (unsigned short)( start + fread(&RAM[start], 1, 65536-start, f) ); /* TODO may overwrite ROM */
|
||||
printf("LOADING FROM $%04X to $%04X\n", start, end);
|
||||
fclose(f);
|
||||
|
||||
|
@ -696,14 +696,14 @@ missing_file_name:
|
|||
|
||||
/* SAVE */
|
||||
static void
|
||||
SAVE() {
|
||||
SAVE(void) {
|
||||
FILE *f;
|
||||
unsigned char savedbyte;
|
||||
unsigned short start;
|
||||
unsigned short end;
|
||||
|
||||
start = RAM[A] | RAM[A+1]<<8;
|
||||
end = X | Y << 8;
|
||||
start = (unsigned short)( RAM[A] | (((unsigned short)RAM[A+1])<<8) );
|
||||
end = (unsigned short)( X | (((unsigned short)Y) << 8) );
|
||||
if (end<start) {
|
||||
C = 1;
|
||||
A = KERN_ERR_NONE;
|
||||
|
@ -732,7 +732,7 @@ SAVE() {
|
|||
|
||||
/* SETTIM */
|
||||
static void
|
||||
SETTIM() {
|
||||
SETTIM(void) {
|
||||
unsigned long jiffies = Y*65536 + X*256 + A;
|
||||
unsigned long seconds = jiffies/60;
|
||||
#ifdef _WIN32
|
||||
|
@ -751,9 +751,9 @@ SETTIM() {
|
|||
|
||||
localtime_r(&now, &bd);
|
||||
|
||||
bd.tm_sec = seconds%60;
|
||||
bd.tm_min = seconds/60;
|
||||
bd.tm_hour = seconds/3600;
|
||||
bd.tm_sec = (int)(seconds%60);
|
||||
bd.tm_min = (int)(seconds/60);
|
||||
bd.tm_hour = (int)(seconds/3600);
|
||||
|
||||
tv.tv_sec = mktime(&bd);
|
||||
tv.tv_usec = (jiffies % 60) * (1000000/60);
|
||||
|
@ -764,7 +764,7 @@ SETTIM() {
|
|||
|
||||
/* RDTIM */
|
||||
static void
|
||||
RDTIM() {
|
||||
RDTIM(void) {
|
||||
unsigned long jiffies;
|
||||
#ifdef _WIN32
|
||||
SYSTEMTIME st;
|
||||
|
@ -779,7 +779,7 @@ RDTIM() {
|
|||
localtime_r(&now, &bd);
|
||||
gettimeofday(&tv, 0);
|
||||
|
||||
jiffies = ((bd.tm_hour*60 + bd.tm_min)*60 + bd.tm_sec)*60 + tv.tv_usec / (1000000/60);
|
||||
jiffies = (unsigned long)( ((bd.tm_hour*60 + bd.tm_min)*60 + bd.tm_sec)*60 + tv.tv_usec / (1000000/60) );
|
||||
#endif
|
||||
Y = (unsigned char)(jiffies/65536);
|
||||
X = (unsigned char)((jiffies%65536)/256);
|
||||
|
@ -789,13 +789,13 @@ RDTIM() {
|
|||
|
||||
/* STOP */
|
||||
static void
|
||||
STOP() {
|
||||
STOP(void) {
|
||||
SETZ(0); /* TODO we don't support the STOP key */
|
||||
}
|
||||
|
||||
/* GETIN */
|
||||
static void
|
||||
GETIN() {
|
||||
GETIN(void) {
|
||||
if (kernal_input != 0) {
|
||||
if (feof(kernal_files[kernal_input])) {
|
||||
kernal_status |= KERN_ST_EOF;
|
||||
|
@ -804,7 +804,7 @@ GETIN() {
|
|||
} else {
|
||||
if (kernal_files_next[kernal_input] == EOF)
|
||||
kernal_files_next[kernal_input] = fgetc(kernal_files[kernal_input]);
|
||||
A = kernal_files_next[kernal_input];
|
||||
A = (unsigned char) kernal_files_next[kernal_input];
|
||||
kernal_files_next[kernal_input] = fgetc(kernal_files[kernal_input]);
|
||||
if (kernal_files_next[kernal_input] == EOF)
|
||||
kernal_status |= KERN_ST_EOF;
|
||||
|
@ -813,11 +813,11 @@ GETIN() {
|
|||
} else {
|
||||
#ifdef _WIN32
|
||||
if (_kbhit())
|
||||
A = _getch();
|
||||
A = (unsigned char) _getch();
|
||||
else
|
||||
A = 0;
|
||||
#else
|
||||
A = getchar();
|
||||
A = (unsigned char) getchar();
|
||||
#endif
|
||||
if (A=='\n') A = '\r';
|
||||
C = 0;
|
||||
|
@ -826,8 +826,8 @@ GETIN() {
|
|||
|
||||
/* CLALL */
|
||||
static void
|
||||
CLALL() {
|
||||
int i;
|
||||
CLALL(void) {
|
||||
size_t i;
|
||||
for (i = 0; i < sizeof(kernal_files)/sizeof(kernal_files[0]); ++i) {
|
||||
if (kernal_files[i]) {
|
||||
fclose(kernal_files[i]);
|
||||
|
@ -838,12 +838,12 @@ CLALL() {
|
|||
|
||||
/* PLOT */
|
||||
static void
|
||||
PLOT() {
|
||||
PLOT(void) {
|
||||
if (C) {
|
||||
int CX, CY;
|
||||
get_cursor(&CX, &CY);
|
||||
Y = CX;
|
||||
X = CY;
|
||||
Y = (unsigned char) CX;
|
||||
X = (unsigned char) CY;
|
||||
} else {
|
||||
printf("UNIMPL: set cursor %d %d\n", Y, X);
|
||||
exit(1);
|
||||
|
@ -853,7 +853,7 @@ PLOT() {
|
|||
|
||||
/* IOBASE */
|
||||
static void
|
||||
IOBASE() {
|
||||
IOBASE(void) {
|
||||
#define CIA 0xDC00 /* we could put this anywhere... */
|
||||
/*
|
||||
* IOBASE is just used inside RND to get a timer value.
|
||||
|
@ -863,19 +863,19 @@ IOBASE() {
|
|||
*/
|
||||
int pseudo_timer;
|
||||
pseudo_timer = rand();
|
||||
RAM[CIA+4] = pseudo_timer&0xff;
|
||||
RAM[CIA+5] = pseudo_timer>>8;
|
||||
RAM[CIA+4] = (unsigned char) (pseudo_timer&0xff);
|
||||
RAM[CIA+5] = (unsigned char) (pseudo_timer>>8);
|
||||
pseudo_timer = rand(); /* more entropy! */
|
||||
RAM[CIA+8] = pseudo_timer&0xff;
|
||||
RAM[CIA+9] = pseudo_timer>>8;
|
||||
RAM[CIA+8] = (unsigned char) (pseudo_timer&0xff);
|
||||
RAM[CIA+9] = (unsigned char) (pseudo_timer>>8);
|
||||
X = CIA & 0xFF;
|
||||
Y = CIA >> 8;
|
||||
}
|
||||
|
||||
int
|
||||
kernal_dispatch() {
|
||||
kernal_dispatch(void) {
|
||||
//{ printf("kernal_dispatch $%04X; ", PC); int i; printf("stack (%02X): ", S); for (i=S+1; i<0x100; i++) { printf("%02X ", RAM[0x0100+i]); } printf("\n"); }
|
||||
unsigned int new_pc;
|
||||
unsigned short new_pc;
|
||||
switch(PC) {
|
||||
case 0x0073: CHRGET(); break;
|
||||
case 0x0079: CHRGOT(); break;
|
||||
|
|
|
@ -1 +1 @@
|
|||
void handle_monitor();
|
||||
void handle_monitor(void *state);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "../perfect6502.h"
|
||||
/* XXX hook up memory[] with RAM[] in runtime.c */
|
||||
|
@ -9,7 +10,7 @@
|
|||
*
|
||||
************************************************************/
|
||||
|
||||
extern int kernal_dispatch();
|
||||
extern int kernal_dispatch(void);
|
||||
|
||||
/* imported by runtime.c */
|
||||
unsigned char A, X, Y, S, P;
|
||||
|
@ -17,10 +18,14 @@ unsigned short PC;
|
|||
int N, Z, C;
|
||||
|
||||
void
|
||||
init_monitor()
|
||||
init_monitor(void)
|
||||
{
|
||||
FILE *f;
|
||||
f = fopen("cbmbasic/cbmbasic.bin", "r");
|
||||
f = fopen("cbmbasic/cbmbasic.bin", "rb");
|
||||
if (f == NULL) {
|
||||
fprintf(stderr,"Could not open cmbasic file\n");
|
||||
exit(-1);
|
||||
}
|
||||
fread(memory + 0xA000, 1, 17591, f);
|
||||
fclose(f);
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
void init_monitor();
|
||||
void init_monitor(void);
|
||||
|
|
6726
netlist_6502.h
6726
netlist_6502.h
File diff suppressed because it is too large
Load Diff
462
netlist_sim.c
462
netlist_sim.c
|
@ -42,16 +42,24 @@ typedef uint16_t count_t;
|
|||
*
|
||||
************************************************************/
|
||||
|
||||
#if 1 /* faster on 64 bit CPUs */
|
||||
#if 1 /* faster on 64 bit CPUs */
|
||||
typedef unsigned long long bitmap_t;
|
||||
#define BITMAP_SHIFT 6
|
||||
#define BITMAP_MASK 63
|
||||
#define ONE 1ULL
|
||||
#else
|
||||
typedef unsigned int bitmap_t;
|
||||
|
||||
#elif 0 /* faster on most 32 bit CPUs */
|
||||
typedef uint32_t bitmap_t;
|
||||
#define BITMAP_SHIFT 5
|
||||
#define BITMAP_MASK 31
|
||||
#define ONE 1UL
|
||||
|
||||
#else /* faster in some cases (and compilers) that allow for vectorization */
|
||||
typedef uint8_t bitmap_t;
|
||||
#define BITMAP_SHIFT 3
|
||||
#define BITMAP_MASK 7
|
||||
#define ONE 1U
|
||||
|
||||
#endif
|
||||
|
||||
/* list of nodes that need to be recalculated */
|
||||
|
@ -83,20 +91,14 @@ typedef struct {
|
|||
bitmap_t *nodes_pullup;
|
||||
bitmap_t *nodes_pulldown;
|
||||
bitmap_t *nodes_value;
|
||||
nodenum_t **nodes_gates;
|
||||
c1c2_t *nodes_c1c2s;
|
||||
count_t *nodes_gatecount;
|
||||
count_t *nodes_c1c2offset;
|
||||
nodenum_t *nodes_dependants;
|
||||
nodenum_t *nodes_left_dependants;
|
||||
nodenum_t **nodes_dependant;
|
||||
nodenum_t **nodes_left_dependant;
|
||||
|
||||
/* everything that describes a transistor */
|
||||
nodenum_t *transistors_gate;
|
||||
nodenum_t *transistors_c1;
|
||||
nodenum_t *transistors_c2;
|
||||
bitmap_t *transistors_on;
|
||||
nodenum_t *nodes_gates;
|
||||
nodenum_t *node_block;
|
||||
c1c2_t *nodes_c1c2s;
|
||||
count_t *nodes_c1c2offset;
|
||||
nodenum_t *nodes_dependant;
|
||||
nodenum_t *nodes_left_dependant;
|
||||
nodenum_t *dependent_block;
|
||||
|
||||
/* the nodes we are working with */
|
||||
nodenum_t *list1;
|
||||
|
@ -112,16 +114,17 @@ typedef struct {
|
|||
count_t groupcount;
|
||||
bitmap_t *groupbitmap;
|
||||
|
||||
enum {
|
||||
contains_nothing,
|
||||
contains_hi,
|
||||
contains_pullup,
|
||||
contains_pulldown,
|
||||
contains_vcc,
|
||||
contains_vss
|
||||
} group_contains_value;
|
||||
} state_t;
|
||||
|
||||
typedef enum {
|
||||
contains_nothing = 0,
|
||||
contains_hi = 1,
|
||||
contains_pullup = 2,
|
||||
contains_pulldown = 3,
|
||||
contains_vcc = 4,
|
||||
contains_vss = 5
|
||||
} group_value;
|
||||
|
||||
/************************************************************
|
||||
*
|
||||
* Main Header Include
|
||||
|
@ -262,9 +265,9 @@ listout_clear(state_t *state)
|
|||
static inline void
|
||||
listout_add(state_t *state, nodenum_t i)
|
||||
{
|
||||
if (!get_bitmap(state->listout_bitmap, i)) {
|
||||
state->listout.list[state->listout.count++] = i;
|
||||
if (get_bitmap(state->listout_bitmap, i) == 0) {
|
||||
set_bitmap(state->listout_bitmap, i, 1);
|
||||
state->listout.list[state->listout.count++] = i;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -320,8 +323,8 @@ group_count(state_t *state)
|
|||
*
|
||||
************************************************************/
|
||||
|
||||
static inline void
|
||||
addNodeToGroup(state_t *state, nodenum_t n)
|
||||
static inline group_value
|
||||
addNodeToGroup(state_t *state, nodenum_t n, group_value val)
|
||||
{
|
||||
/*
|
||||
* We need to stop at vss and vcc, otherwise we'll revisit other groups
|
||||
|
@ -329,55 +332,61 @@ addNodeToGroup(state_t *state, nodenum_t n)
|
|||
* the fact that they are connected to vcc or vss.
|
||||
*/
|
||||
if (n == state->vss) {
|
||||
state->group_contains_value = contains_vss;
|
||||
return;
|
||||
return contains_vss;
|
||||
}
|
||||
|
||||
if (n == state->vcc) {
|
||||
if (state->group_contains_value != contains_vss)
|
||||
state->group_contains_value = contains_vcc;
|
||||
return;
|
||||
if (val != contains_vss)
|
||||
val = contains_vcc;
|
||||
return val;
|
||||
}
|
||||
|
||||
/* check and see if we already have this node, and if so return */
|
||||
if (group_contains(state, n))
|
||||
return;
|
||||
return val;
|
||||
|
||||
group_add(state, n);
|
||||
|
||||
if (state->group_contains_value < contains_pulldown && get_nodes_pulldown(state, n)) {
|
||||
state->group_contains_value = contains_pulldown;
|
||||
}
|
||||
if (state->group_contains_value < contains_pullup && get_nodes_pullup(state, n)) {
|
||||
state->group_contains_value = contains_pullup;
|
||||
}
|
||||
if (state->group_contains_value < contains_hi && get_nodes_value(state, n)) {
|
||||
state->group_contains_value = contains_hi;
|
||||
}
|
||||
/* Give the compiler a hint that all of these can be calculated, and don't need to wait on branches.
|
||||
This results in a small speedup.
|
||||
*/
|
||||
BOOL isPulldown = get_nodes_pulldown(state, n);
|
||||
BOOL isPullup = get_nodes_pullup(state, n);
|
||||
BOOL nodeValue = get_nodes_value(state, n);
|
||||
if (val < contains_pulldown && isPulldown)
|
||||
val = contains_pulldown;
|
||||
if (val < contains_pullup && isPullup)
|
||||
val = contains_pullup;
|
||||
if (val < contains_hi && nodeValue)
|
||||
val = contains_hi;
|
||||
/* state can remain at contains_nothing if the node value is low */
|
||||
|
||||
/* revisit all transistors that control this node */
|
||||
count_t end = state->nodes_c1c2offset[n+1];
|
||||
for (count_t t = state->nodes_c1c2offset[n]; t < end; t++) {
|
||||
c1c2_t c = state->nodes_c1c2s[t];
|
||||
const count_t start = state->nodes_c1c2offset[n];
|
||||
const count_t end = state->nodes_c1c2offset[n+1];
|
||||
const c1c2_t *node_c1c2s = state->nodes_c1c2s;
|
||||
for (count_t t = start; t < end; t++) {
|
||||
const c1c2_t c = node_c1c2s[t];
|
||||
/* if the transistor connects c1 and c2... */
|
||||
if (get_transistors_on(state, c.transistor)) {
|
||||
addNodeToGroup(state, c.other_node);
|
||||
val = addNodeToGroup(state, c.other_node, val);
|
||||
}
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static inline void
|
||||
static inline group_value
|
||||
addAllNodesToGroup(state_t *state, nodenum_t node)
|
||||
{
|
||||
group_clear(state);
|
||||
|
||||
state->group_contains_value = contains_nothing;
|
||||
|
||||
addNodeToGroup(state, node);
|
||||
return addNodeToGroup(state, node, contains_nothing);
|
||||
}
|
||||
|
||||
static inline BOOL
|
||||
getGroupValue(state_t *state)
|
||||
getGroupValue(group_value node_value)
|
||||
{
|
||||
switch (state->group_contains_value) {
|
||||
switch (node_value) {
|
||||
case contains_vcc:
|
||||
case contains_pullup:
|
||||
case contains_hi:
|
||||
|
@ -396,10 +405,10 @@ recalcNode(state_t *state, nodenum_t node)
|
|||
* get all nodes that are connected through
|
||||
* transistors, starting with this one
|
||||
*/
|
||||
addAllNodesToGroup(state, node);
|
||||
group_value node_value = addAllNodesToGroup(state, node);
|
||||
|
||||
/* get the state of the group */
|
||||
BOOL newv = getGroupValue(state);
|
||||
BOOL newv = getGroupValue(node_value);
|
||||
|
||||
/*
|
||||
* - set all nodes to the group state
|
||||
|
@ -407,22 +416,29 @@ recalcNode(state_t *state, nodenum_t node)
|
|||
* - collect all nodes behind toggled transistors
|
||||
* for the next run
|
||||
*/
|
||||
for (count_t i = 0; i < group_count(state); i++) {
|
||||
nodenum_t nn = group_get(state, i);
|
||||
const count_t grp_count = group_count(state);
|
||||
for (count_t i = 0; i < grp_count; i++) {
|
||||
const nodenum_t nn = group_get(state, i);
|
||||
if (get_nodes_value(state, nn) != newv) {
|
||||
set_nodes_value(state, nn, newv);
|
||||
for (count_t t = 0; t < state->nodes_gatecount[nn]; t++) {
|
||||
transnum_t tn = state->nodes_gates[nn][t];
|
||||
const nodenum_t startg = state->nodes_gates[nn];
|
||||
const nodenum_t endg = state->nodes_gates[nn+1];
|
||||
for (count_t t = startg; t < endg; t++) {
|
||||
transnum_t tn = state->node_block[t];
|
||||
set_transistors_on(state, tn, newv);
|
||||
}
|
||||
|
||||
if (newv) {
|
||||
for (count_t g = 0; g < state->nodes_left_dependants[nn]; g++) {
|
||||
listout_add(state, state->nodes_left_dependant[nn][g]);
|
||||
const nodenum_t dep_offset = state->nodes_left_dependant[nn];
|
||||
const nodenum_t dep_end = state->nodes_left_dependant[nn+1];
|
||||
for (count_t g = dep_offset; g < dep_end; g++) {
|
||||
listout_add(state, state->dependent_block[g]);
|
||||
}
|
||||
} else {
|
||||
for (count_t g = 0; g < state->nodes_dependants[nn]; g++) {
|
||||
listout_add(state, state->nodes_dependant[nn][g]);
|
||||
const nodenum_t dep_offset = state->nodes_dependant[nn];
|
||||
const nodenum_t dep_end = state->nodes_dependant[nn+1];
|
||||
for (count_t g = dep_offset; g < dep_end; g++) {
|
||||
listout_add(state, state->dependent_block[g]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -432,7 +448,10 @@ recalcNode(state_t *state, nodenum_t node)
|
|||
void
|
||||
recalcNodeList(state_t *state)
|
||||
{
|
||||
for (int j = 0; j < 100; j++) { /* loop limiter */
|
||||
const int max_iterations = 50;
|
||||
int j;
|
||||
|
||||
for (j = 0; j < max_iterations; j++) { /* loop limiter */
|
||||
/*
|
||||
* make the secondary list our primary list, use
|
||||
* the data storage of the primary list as the
|
||||
|
@ -452,11 +471,18 @@ recalcNodeList(state_t *state)
|
|||
* all transistors controlled by this path, collecting
|
||||
* all nodes that changed because of it for the next run
|
||||
*/
|
||||
for (count_t i = 0; i < listin_count(state); i++) {
|
||||
const count_t list_count = listin_count(state);
|
||||
for (count_t i = 0; i < list_count; i++) {
|
||||
nodenum_t n = listin_get(state, i);
|
||||
recalcNode(state, n);
|
||||
}
|
||||
}
|
||||
|
||||
if (j == max_iterations) {
|
||||
fprintf(stderr,"### recalcNodeList max iterations hit, listin.count = %d\n", listin_count(state));
|
||||
}
|
||||
|
||||
/* without this, we'll have a bogus listin on the next step */
|
||||
listout_clear(state);
|
||||
}
|
||||
|
||||
|
@ -467,25 +493,31 @@ recalcNodeList(state_t *state)
|
|||
************************************************************/
|
||||
|
||||
static inline void
|
||||
add_nodes_dependant(state_t *state, nodenum_t a, nodenum_t b)
|
||||
add_nodes_dependant(state_t *state, nodenum_t a, nodenum_t b, nodenum_t *counts, nodenum_t offset )
|
||||
{
|
||||
for (count_t g = 0; g < state->nodes_dependants[a]; g++)
|
||||
if (state->nodes_dependant[a][g] == b)
|
||||
return;
|
||||
/* O(N^2) behavior, but only run during initialization
|
||||
NOTE - counts are still being set and cannot be calculated from offsets
|
||||
*/
|
||||
nodenum_t *dependent_data = state->dependent_block + offset;
|
||||
const nodenum_t dep_count = counts[a];
|
||||
for (count_t g = 0; g < dep_count; g++)
|
||||
if (dependent_data[g] == b)
|
||||
return;
|
||||
|
||||
state->nodes_dependant[a][state->nodes_dependants[a]++] = b;
|
||||
dependent_data[ counts[a]++ ] = b;
|
||||
}
|
||||
|
||||
static inline void
|
||||
add_nodes_left_dependant(state_t *state, nodenum_t a, nodenum_t b)
|
||||
{
|
||||
for (count_t g = 0; g < state->nodes_left_dependants[a]; g++)
|
||||
if (state->nodes_left_dependant[a][g] == b)
|
||||
return;
|
||||
|
||||
state->nodes_left_dependant[a][state->nodes_left_dependants[a]++] = b;
|
||||
}
|
||||
/* 6502:
|
||||
3288 transistors, 3239 used in simulation after duplicate removal
|
||||
1725 entries in node list and used in simulation
|
||||
c1c2total = 6478
|
||||
block_gate_size = 3239
|
||||
block_dep_size = 7260
|
||||
|
||||
Working set = 89 KB allocations, 220 KB binary, plus system libs and text buffering
|
||||
= 604 KB in release build
|
||||
*/
|
||||
state_t *
|
||||
setupNodesAndTransistors(netlist_transdefs *transdefs, BOOL *node_is_pullup, nodenum_t nodes, nodenum_t transistors, nodenum_t vss, nodenum_t vcc)
|
||||
{
|
||||
|
@ -495,120 +527,227 @@ setupNodesAndTransistors(netlist_transdefs *transdefs, BOOL *node_is_pullup, nod
|
|||
state->transistors = transistors;
|
||||
state->vss = vss;
|
||||
state->vcc = vcc;
|
||||
|
||||
state->nodes_c1c2offset = calloc(state->nodes + 1, sizeof(*state->nodes_c1c2offset));
|
||||
state->nodes_pullup = calloc(WORDS_FOR_BITS(state->nodes), sizeof(*state->nodes_pullup));
|
||||
state->nodes_pulldown = calloc(WORDS_FOR_BITS(state->nodes), sizeof(*state->nodes_pulldown));
|
||||
state->nodes_value = calloc(WORDS_FOR_BITS(state->nodes), sizeof(*state->nodes_value));
|
||||
state->nodes_gates = malloc(state->nodes * sizeof(*state->nodes_gates));
|
||||
for (count_t i = 0; i < state->nodes; i++) {
|
||||
state->nodes_gates[i] = calloc(state->nodes, sizeof(**state->nodes_gates));
|
||||
}
|
||||
state->nodes_gatecount = calloc(state->nodes, sizeof(*state->nodes_gatecount));
|
||||
state->nodes_c1c2offset = calloc(state->nodes + 1, sizeof(*state->nodes_c1c2offset));
|
||||
state->nodes_dependants = calloc(state->nodes, sizeof(*state->nodes_dependants));
|
||||
state->nodes_left_dependants = calloc(state->nodes, sizeof(*state->nodes_left_dependants));
|
||||
state->nodes_dependant = malloc(state->nodes * sizeof(*state->nodes_dependant));
|
||||
for (count_t i = 0; i < state->nodes; i++) {
|
||||
state->nodes_dependant[i] = calloc(state->nodes, sizeof(**state->nodes_dependant));
|
||||
}
|
||||
state->nodes_left_dependant = malloc(state->nodes * sizeof(*state->nodes_left_dependant));
|
||||
for (count_t i = 0; i < state->nodes; i++) {
|
||||
state->nodes_left_dependant[i] = calloc(state->nodes, sizeof(**state->nodes_left_dependant));
|
||||
}
|
||||
state->transistors_gate = calloc(state->transistors, sizeof(*state->transistors_gate));
|
||||
state->transistors_c1 = calloc(state->transistors, sizeof(*state->transistors_c1));
|
||||
state->transistors_c2 = calloc(state->transistors, sizeof(*state->transistors_c2));
|
||||
state->transistors_on = calloc(WORDS_FOR_BITS(state->transistors), sizeof(*state->transistors_on));
|
||||
state->listout_bitmap = calloc(WORDS_FOR_BITS(state->nodes), sizeof(*state->listout_bitmap));
|
||||
state->groupbitmap = calloc(WORDS_FOR_BITS(state->nodes), sizeof(*state->groupbitmap));
|
||||
|
||||
/* group content depends on active state, not easy to predict actual size needed */
|
||||
state->group = calloc(state->nodes, sizeof(*state->group));
|
||||
|
||||
/* ping pong state buffers */
|
||||
state->list1 = calloc(state->nodes, sizeof(*state->list1));
|
||||
state->list2 = calloc(state->nodes, sizeof(*state->list2));
|
||||
state->listout_bitmap = calloc(WORDS_FOR_BITS(state->nodes), sizeof(*state->listout_bitmap));
|
||||
state->group = malloc(state->nodes * sizeof(*state->group));
|
||||
state->groupbitmap = calloc(WORDS_FOR_BITS(state->nodes), sizeof(*state->groupbitmap));
|
||||
state->listin.list = state->list1;
|
||||
state->listin.count = 0;
|
||||
state->listout.list = state->list2;
|
||||
state->listout.count = 0;
|
||||
|
||||
|
||||
/* these are only used in initialization */
|
||||
nodenum_t *nodes_dep_count = calloc(state->nodes, sizeof(nodenum_t));
|
||||
nodenum_t *nodes_left_dep_count = calloc(state->nodes, sizeof(nodenum_t));
|
||||
count_t *nodes_gatecount = calloc(state->nodes, sizeof(count_t));
|
||||
nodenum_t *transistors_gate = calloc(state->transistors, sizeof(nodenum_t));
|
||||
nodenum_t *transistors_c1 = calloc(state->transistors, sizeof(nodenum_t));
|
||||
nodenum_t *transistors_c2 = calloc(state->transistors, sizeof(nodenum_t));
|
||||
|
||||
count_t i;
|
||||
|
||||
/* copy nodes into r/w data structure */
|
||||
for (i = 0; i < state->nodes; i++) {
|
||||
set_nodes_pullup(state, i, node_is_pullup[i]);
|
||||
state->nodes_gatecount[i] = 0;
|
||||
nodes_gatecount[i] = 0;
|
||||
}
|
||||
/* copy transistors into r/w data structure */
|
||||
count_t j = 0;
|
||||
|
||||
/* Copy transistors into r/w data structure and remove duplicates */
|
||||
count_t transistors_used = 0;
|
||||
for (i = 0; i < state->transistors; i++) {
|
||||
nodenum_t gate = transdefs[i].gate;
|
||||
nodenum_t c1 = transdefs[i].c1;
|
||||
nodenum_t c2 = transdefs[i].c2;
|
||||
/* skip duplicate transistors */
|
||||
/* skip duplicate transistors (including ones with reversed c1c2 values)
|
||||
O(N^2) operation, but only done once at initialization, not a significant time sink */
|
||||
BOOL found = NO;
|
||||
for (count_t j2 = 0; j2 < j; j2++) {
|
||||
if (state->transistors_gate[j2] == gate &&
|
||||
((state->transistors_c1[j2] == c1 &&
|
||||
state->transistors_c2[j2] == c2) ||
|
||||
(state->transistors_c1[j2] == c2 &&
|
||||
state->transistors_c2[j2] == c1))) {
|
||||
for (count_t j2 = 0; j2 < transistors_used; j2++) {
|
||||
if (transistors_gate[j2] == gate &&
|
||||
((transistors_c1[j2] == c1 &&
|
||||
transistors_c2[j2] == c2) ||
|
||||
(transistors_c1[j2] == c2 &&
|
||||
transistors_c2[j2] == c1))) {
|
||||
found = YES;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
state->transistors_gate[j] = gate;
|
||||
state->transistors_c1[j] = c1;
|
||||
state->transistors_c2[j] = c2;
|
||||
j++;
|
||||
transistors_gate[transistors_used] = gate;
|
||||
transistors_c1[transistors_used] = c1;
|
||||
transistors_c2[transistors_used] = c2;
|
||||
transistors_used++;
|
||||
}
|
||||
}
|
||||
state->transistors = j;
|
||||
state->transistors = transistors_used;
|
||||
|
||||
|
||||
/* cross reference transistors in nodes data structures */
|
||||
/* start by computing how many c1c2 entries should be created for each node */
|
||||
count_t *c1c2count = calloc(state->nodes, sizeof(*c1c2count));
|
||||
count_t c1c2total = 0;
|
||||
for (i = 0; i < state->transistors; i++) {
|
||||
nodenum_t gate = state->transistors_gate[i];
|
||||
state->nodes_gates[gate][state->nodes_gatecount[gate]++] = i;
|
||||
c1c2count[state->transistors_c1[i]]++;
|
||||
c1c2count[state->transistors_c2[i]]++;
|
||||
nodenum_t gate = transistors_gate[i];
|
||||
nodenum_t c1 = transistors_c1[i];
|
||||
nodenum_t c2 = transistors_c2[i];
|
||||
|
||||
if (gate >= nodes || c1 >= nodes || c2 >= nodes)
|
||||
fprintf(stderr,"FATAL - bad transistor definition %d\n", i);
|
||||
|
||||
nodes_gatecount[gate]++;
|
||||
c1c2count[c1]++;
|
||||
c1c2count[c2]++;
|
||||
c1c2total += 2;
|
||||
}
|
||||
|
||||
/* then sum the counts to find each node's offset into the c1c2 array */
|
||||
count_t c1c2offset = 0;
|
||||
for (i = 0; i < state->nodes; i++) {
|
||||
state->nodes_c1c2offset[i] = c1c2offset;
|
||||
c1c2offset += c1c2count[i];
|
||||
}
|
||||
state->nodes_c1c2offset[i] = c1c2offset;
|
||||
state->nodes_c1c2offset[i] = c1c2offset; /* fill the end entry, so we can calculate distances/counts */
|
||||
|
||||
/* create and fill the nodes_c1c2s array according to these offsets */
|
||||
state->nodes_c1c2s = calloc(c1c2total, sizeof(*state->nodes_c1c2s));
|
||||
memset(c1c2count, 0, state->nodes * sizeof(*c1c2count));
|
||||
memset(c1c2count, 0, state->nodes * sizeof(*c1c2count)); /* zero counts so we can reuse them */
|
||||
for (i = 0; i < state->transistors; i++) {
|
||||
nodenum_t c1 = state->transistors_c1[i];
|
||||
nodenum_t c2 = state->transistors_c2[i];
|
||||
nodenum_t c1 = transistors_c1[i];
|
||||
nodenum_t c2 = transistors_c2[i];
|
||||
state->nodes_c1c2s[state->nodes_c1c2offset[c1] + c1c2count[c1]++] = c1c2(i, c2);
|
||||
state->nodes_c1c2s[state->nodes_c1c2offset[c2] + c1c2count[c2]++] = c1c2(i, c1);
|
||||
}
|
||||
/* this is unused after initialization */
|
||||
free(c1c2count);
|
||||
c1c2count = NULL;
|
||||
|
||||
|
||||
/* Sum the counts for total allocation of gates */
|
||||
size_t block_gate_size = 0;
|
||||
for (i = 0; i < state->nodes; i++) {
|
||||
block_gate_size += (size_t) nodes_gatecount[i];
|
||||
}
|
||||
|
||||
/* Allocate the block of gate data all at once */
|
||||
state->node_block = calloc( block_gate_size, sizeof(*state->nodes_gates) );
|
||||
|
||||
/* Assign offsets from our block */
|
||||
state->nodes_gates = malloc((nodes+1) * sizeof(*state->nodes_gates));
|
||||
nodenum_t node_index = 0;
|
||||
for (i = 0; i < state->nodes; i++) {
|
||||
count_t count = nodes_gatecount[i];
|
||||
state->nodes_gates[i] = node_index;
|
||||
node_index += count;
|
||||
}
|
||||
state->nodes_gates[state->nodes] = node_index; /* fill the end entry, so we can calculate distances/counts */
|
||||
|
||||
/* Cross reference transistors in nodes with smaller data structures */
|
||||
memset(nodes_gatecount, 0, state->nodes * sizeof(count_t));
|
||||
for (i = 0; i < state->transistors; i++) {
|
||||
nodenum_t gate = transistors_gate[i];
|
||||
nodenum_t *gate_data = state->node_block + state->nodes_gates[gate];
|
||||
gate_data[ nodes_gatecount[gate]++ ] = i;
|
||||
}
|
||||
|
||||
|
||||
for (i = 0; i < state->nodes; i++) {
|
||||
state->nodes_dependants[i] = 0;
|
||||
state->nodes_left_dependants[i] = 0;
|
||||
for (count_t g = 0; g < state->nodes_gatecount[i]; g++) {
|
||||
transnum_t t = state->nodes_gates[i][g];
|
||||
nodenum_t c1 = state->transistors_c1[t];
|
||||
if (c1 != vss && c1 != vcc) {
|
||||
add_nodes_dependant(state, i, c1);
|
||||
}
|
||||
nodenum_t c2 = state->transistors_c2[t];
|
||||
if (c2 != vss && c2 != vcc) {
|
||||
add_nodes_dependant(state, i, c2);
|
||||
}
|
||||
if (c1 != vss && c1 != vcc) {
|
||||
add_nodes_left_dependant(state, i, c1);
|
||||
} else {
|
||||
add_nodes_left_dependant(state, i, c2);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* See how many dependent node entries we really need.
|
||||
Must happen after gatecount and nodes_gates assignments!
|
||||
*/
|
||||
for (i = 0; i < state->nodes; i++) {
|
||||
nodes_dep_count[i] = 0;
|
||||
nodes_left_dep_count[i] = 0;
|
||||
nodenum_t *gate_data = state->node_block + state->nodes_gates[i];
|
||||
for (count_t g = 0; g < nodes_gatecount[i]; g++) {
|
||||
nodenum_t t = gate_data[g];
|
||||
nodenum_t c1 = transistors_c1[t];
|
||||
if (c1 != vss && c1 != vcc) {
|
||||
nodes_dep_count[i]++;
|
||||
}
|
||||
nodenum_t c2 = transistors_c2[t];
|
||||
if (c2 != vss && c2 != vcc) {
|
||||
nodes_dep_count[i]++;
|
||||
}
|
||||
nodes_left_dep_count[i]++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Sum the counts to find total size of the dependents array */
|
||||
size_t block_dep_size = 0;
|
||||
for (i = 0; i < state->nodes; i++) {
|
||||
block_dep_size += nodes_dep_count[i];
|
||||
block_dep_size += nodes_left_dep_count[i];
|
||||
}
|
||||
|
||||
/* Allocate the dependents block all at once */
|
||||
state->dependent_block = calloc( block_dep_size, sizeof(*state->nodes_dependant) );
|
||||
|
||||
/* Assign offsets from our block, using only counts needed */
|
||||
state->nodes_dependant = malloc((nodes+1) * sizeof(*state->nodes_dependant));
|
||||
nodenum_t dep_index = 0;
|
||||
for (i = 0; i < state->nodes; i++) {
|
||||
nodenum_t count = nodes_dep_count[i];
|
||||
state->nodes_dependant[i] = dep_index;
|
||||
dep_index += count;
|
||||
}
|
||||
state->nodes_dependant[state->nodes] = dep_index; /* fill the end entry, so we can calculate distances/counts */
|
||||
|
||||
/* Assign offsets from our block, using only counts needed */
|
||||
state->nodes_left_dependant = malloc((nodes+1) * sizeof(*state->nodes_left_dependant));
|
||||
for (i = 0; i < state->nodes; i++) {
|
||||
nodenum_t count = nodes_left_dep_count[i];
|
||||
state->nodes_left_dependant[i] = dep_index;
|
||||
dep_index += count;
|
||||
}
|
||||
state->nodes_left_dependant[state->nodes] = dep_index; /* fill the end entry, so we can calculate distances/counts */
|
||||
|
||||
/* Copy dependencies into smaller data structures */
|
||||
for (i = 0; i < state->nodes; i++) {
|
||||
nodes_dep_count[i] = 0;
|
||||
nodes_left_dep_count[i] = 0;
|
||||
nodenum_t *gate_data = state->node_block + state->nodes_gates[i];
|
||||
for (count_t g = 0; g < nodes_gatecount[i]; g++) {
|
||||
nodenum_t t = gate_data[g];
|
||||
nodenum_t c1 = transistors_c1[t];
|
||||
if (c1 != vss && c1 != vcc) {
|
||||
add_nodes_dependant(state, i, c1, nodes_dep_count, state->nodes_dependant[i]);
|
||||
}
|
||||
nodenum_t c2 = transistors_c2[t];
|
||||
if (c2 != vss && c2 != vcc) {
|
||||
add_nodes_dependant(state, i, c2, nodes_dep_count, state->nodes_dependant[i]);
|
||||
}
|
||||
if (c1 != vss && c1 != vcc) {
|
||||
add_nodes_dependant(state, i, c1, nodes_left_dep_count, state->nodes_left_dependant[i]);
|
||||
} else {
|
||||
add_nodes_dependant(state, i, c2, nodes_left_dep_count, state->nodes_left_dependant[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* these are unused after initialization */
|
||||
free(nodes_dep_count);
|
||||
nodes_dep_count = NULL;
|
||||
free(nodes_left_dep_count);
|
||||
nodes_left_dep_count = NULL;
|
||||
free(nodes_gatecount);
|
||||
nodes_gatecount = NULL;
|
||||
free(transistors_gate);
|
||||
transistors_gate = NULL;
|
||||
free(transistors_c1);
|
||||
transistors_c1 = NULL;
|
||||
free(transistors_c2);
|
||||
transistors_c2 = NULL;
|
||||
|
||||
|
||||
#if 0 /* unnecessary - RESET will stabilize the network anyway */
|
||||
/* all nodes are down */
|
||||
|
@ -617,7 +756,7 @@ setupNodesAndTransistors(netlist_transdefs *transdefs, BOOL *node_is_pullup, nod
|
|||
}
|
||||
/* all transistors are off */
|
||||
for (transnum_t tn = 0; tn < state->transistors; tn++)
|
||||
set_transistors_on(state, tn, NO);
|
||||
set_transistors_on(state, tn, NO);
|
||||
#endif
|
||||
|
||||
return state;
|
||||
|
@ -629,26 +768,11 @@ destroyNodesAndTransistors(state_t *state)
|
|||
free(state->nodes_pullup);
|
||||
free(state->nodes_pulldown);
|
||||
free(state->nodes_value);
|
||||
for (count_t i = 0; i < state->nodes; i++) {
|
||||
free(state->nodes_gates[i]);
|
||||
}
|
||||
free(state->nodes_gates);
|
||||
free(state->node_block);
|
||||
free(state->nodes_c1c2s);
|
||||
free(state->nodes_gatecount);
|
||||
free(state->nodes_c1c2offset);
|
||||
free(state->nodes_dependants);
|
||||
free(state->nodes_left_dependants);
|
||||
for (count_t i = 0; i < state->nodes; i++) {
|
||||
free(state->nodes_dependant[i]);
|
||||
}
|
||||
free(state->nodes_dependant);
|
||||
for (count_t i = 0; i < state->nodes; i++) {
|
||||
free(state->nodes_left_dependant[i]);
|
||||
}
|
||||
free(state->nodes_left_dependant);
|
||||
free(state->transistors_gate);
|
||||
free(state->transistors_c1);
|
||||
free(state->transistors_c2);
|
||||
free(state->dependent_block);
|
||||
free(state->transistors_on);
|
||||
free(state->list1);
|
||||
free(state->list2);
|
||||
|
@ -662,7 +786,7 @@ void
|
|||
stabilizeChip(state_t *state)
|
||||
{
|
||||
for (count_t i = 0; i < state->nodes; i++)
|
||||
listout_add(state, i);
|
||||
listout_add(state, i);
|
||||
|
||||
recalcNodeList(state);
|
||||
}
|
||||
|
@ -676,11 +800,11 @@ stabilizeChip(state_t *state)
|
|||
void
|
||||
setNode(state_t *state, nodenum_t nn, BOOL s)
|
||||
{
|
||||
set_nodes_pullup(state, nn, s);
|
||||
set_nodes_pulldown(state, nn, !s);
|
||||
listout_add(state, nn);
|
||||
set_nodes_pullup(state, nn, s);
|
||||
set_nodes_pulldown(state, nn, !s);
|
||||
listout_add(state, nn);
|
||||
|
||||
recalcNodeList(state);
|
||||
recalcNodeList(state);
|
||||
}
|
||||
|
||||
BOOL
|
||||
|
@ -698,7 +822,7 @@ isNodeHigh(state_t *state, nodenum_t nn)
|
|||
unsigned int
|
||||
readNodes(state_t *state, int count, nodenum_t *nodelist)
|
||||
{
|
||||
int result = 0;
|
||||
unsigned int result = 0;
|
||||
for (int i = count - 1; i >= 0; i--) {
|
||||
result <<= 1;
|
||||
result |= isNodeHigh(state, nodelist[i]);
|
||||
|
@ -710,5 +834,5 @@ void
|
|||
writeNodes(state_t *state, int count, nodenum_t *nodelist, int v)
|
||||
{
|
||||
for (int i = 0; i < 8; i++, v >>= 1)
|
||||
setNode(state, nodelist[i], v & 1);
|
||||
setNode(state, nodelist[i], v & 1);
|
||||
}
|
||||
|
|
|
@ -35,13 +35,13 @@
|
|||
uint16_t
|
||||
readAddressBus(void *state)
|
||||
{
|
||||
return readNodes(state, 16, (nodenum_t[]){ ab0, ab1, ab2, ab3, ab4, ab5, ab6, ab7, ab8, ab9, ab10, ab11, ab12, ab13, ab14, ab15 });
|
||||
return (uint16_t)readNodes(state, 16, (nodenum_t[]){ ab0, ab1, ab2, ab3, ab4, ab5, ab6, ab7, ab8, ab9, ab10, ab11, ab12, ab13, ab14, ab15 });
|
||||
}
|
||||
|
||||
uint8_t
|
||||
readDataBus(void *state)
|
||||
{
|
||||
return readNodes(state, 8, (nodenum_t[]){ db0, db1, db2, db3, db4, db5, db6, db7 });
|
||||
return (uint8_t)readNodes(state, 8, (nodenum_t[]){ db0, db1, db2, db3, db4, db5, db6, db7 });
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -59,55 +59,55 @@ readRW(void *state)
|
|||
uint8_t
|
||||
readA(void *state)
|
||||
{
|
||||
return readNodes(state, 8, (nodenum_t[]){ a0,a1,a2,a3,a4,a5,a6,a7 });
|
||||
return (uint8_t)readNodes(state, 8, (nodenum_t[]){ a0,a1,a2,a3,a4,a5,a6,a7 });
|
||||
}
|
||||
|
||||
uint8_t
|
||||
readX(void *state)
|
||||
{
|
||||
return readNodes(state, 8, (nodenum_t[]){ x0,x1,x2,x3,x4,x5,x6,x7 });
|
||||
return (uint8_t)readNodes(state, 8, (nodenum_t[]){ x0,x1,x2,x3,x4,x5,x6,x7 });
|
||||
}
|
||||
|
||||
uint8_t
|
||||
readY(void *state)
|
||||
{
|
||||
return readNodes(state, 8, (nodenum_t[]){ y0,y1,y2,y3,y4,y5,y6,y7 });
|
||||
return (uint8_t)readNodes(state, 8, (nodenum_t[]){ y0,y1,y2,y3,y4,y5,y6,y7 });
|
||||
}
|
||||
|
||||
uint8_t
|
||||
readP(void *state)
|
||||
{
|
||||
return readNodes(state, 8, (nodenum_t[]){ p0,p1,p2,p3,p4,p5,p6,p7 });
|
||||
return (uint8_t)readNodes(state, 8, (nodenum_t[]){ p0,p1,p2,p3,p4,p5,p6,p7 });
|
||||
}
|
||||
|
||||
uint8_t
|
||||
readIR(void *state)
|
||||
{
|
||||
return readNodes(state, 8, (nodenum_t[]){ notir0,notir1,notir2,notir3,notir4,notir5,notir6,notir7 }) ^ 0xFF;
|
||||
return (uint8_t)readNodes(state, 8, (nodenum_t[]){ notir0,notir1,notir2,notir3,notir4,notir5,notir6,notir7 }) ^ 0xFF;
|
||||
}
|
||||
|
||||
uint8_t
|
||||
readSP(void *state)
|
||||
{
|
||||
return readNodes(state, 8, (nodenum_t[]){ s0,s1,s2,s3,s4,s5,s6,s7 });
|
||||
return (uint8_t)readNodes(state, 8, (nodenum_t[]){ s0,s1,s2,s3,s4,s5,s6,s7 });
|
||||
}
|
||||
|
||||
uint8_t
|
||||
readPCL(void *state)
|
||||
{
|
||||
return readNodes(state, 8, (nodenum_t[]){ pcl0,pcl1,pcl2,pcl3,pcl4,pcl5,pcl6,pcl7 });
|
||||
return (uint8_t)readNodes(state, 8, (nodenum_t[]){ pcl0,pcl1,pcl2,pcl3,pcl4,pcl5,pcl6,pcl7 });
|
||||
}
|
||||
|
||||
uint8_t
|
||||
readPCH(void *state)
|
||||
{
|
||||
return readNodes(state, 8, (nodenum_t[]){ pch0,pch1,pch2,pch3,pch4,pch5,pch6,pch7 });
|
||||
return (uint8_t)readNodes(state, 8, (nodenum_t[]){ pch0,pch1,pch2,pch3,pch4,pch5,pch6,pch7 });
|
||||
}
|
||||
|
||||
uint16_t
|
||||
readPC(void *state)
|
||||
{
|
||||
return (readPCH(state) << 8) | readPCL(state);
|
||||
return (uint16_t)((uint16_t)readPCH(state) << 8) | ((uint16_t)readPCL(state));
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
|
@ -145,7 +145,7 @@ handleMemory(void *state)
|
|||
*
|
||||
************************************************************/
|
||||
|
||||
unsigned int cycle;
|
||||
unsigned long cycle;
|
||||
|
||||
void
|
||||
step(void *state)
|
||||
|
@ -164,7 +164,7 @@ step(void *state)
|
|||
}
|
||||
|
||||
void *
|
||||
initAndResetChip()
|
||||
initAndResetChip(void)
|
||||
{
|
||||
/* set up data structures for efficient emulation */
|
||||
nodenum_t nodes = sizeof(netlist_6502_node_is_pullup)/sizeof(*netlist_6502_node_is_pullup);
|
||||
|
@ -218,7 +218,7 @@ chipStatus(void *state)
|
|||
uint8_t d = readDataBus(state);
|
||||
BOOL r_w = isNodeHigh(state, rw);
|
||||
|
||||
printf("halfcyc:%d phi0:%d AB:%04X D:%02X RnW:%d PC:%04X A:%02X X:%02X Y:%02X SP:%02X P:%02X IR:%02X",
|
||||
printf("halfcyc:%ld phi0:%d AB:%04X D:%02X RnW:%d PC:%04X A:%02X X:%02X Y:%02X SP:%02X P:%02X IR:%02X",
|
||||
cycle,
|
||||
clk,
|
||||
a,
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#define state_t void
|
||||
#endif
|
||||
|
||||
extern state_t *initAndResetChip();
|
||||
extern state_t *initAndResetChip(void);
|
||||
extern void destroyChip(state_t *state);
|
||||
extern void step(state_t *state);
|
||||
extern void chipStatus(state_t *state);
|
||||
|
@ -19,5 +19,5 @@ extern unsigned char readDataBus(state_t *state);
|
|||
extern unsigned char readIR(state_t *state);
|
||||
|
||||
extern unsigned char memory[65536];
|
||||
extern unsigned int cycle;
|
||||
extern unsigned int transistors;
|
||||
extern unsigned long cycle;
|
||||
//extern unsigned int transistors;
|
||||
|
|
10
types.h
10
types.h
|
@ -3,16 +3,16 @@
|
|||
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef unsigned int BOOL;
|
||||
typedef unsigned char BOOL;
|
||||
typedef uint16_t nodenum_t;
|
||||
|
||||
typedef struct {
|
||||
int gate;
|
||||
int c1;
|
||||
int c2;
|
||||
nodenum_t gate;
|
||||
nodenum_t c1;
|
||||
nodenum_t c2;
|
||||
} netlist_transdefs;
|
||||
|
||||
#define YES 1
|
||||
#define NO 0
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue
Block a user