#include #include #include #include #include #include static Display *display; static int screen_number; static Screen *screen; static unsigned long white; static unsigned long black; static Window default_root; static Window win; static XFontStruct *font; static XFontStruct *smallfont; static XGCValues vals; static GC gc; static GC smallgc; void create_main_window(void) { XSetWindowAttributes attributes; display = XOpenDisplay(NULL); screen_number = XDefaultScreen(display); screen = XScreenOfDisplay(display, screen_number); black = XBlackPixelOfScreen(screen); white = XWhitePixelOfScreen(screen); attributes.background_pixel = white; attributes.event_mask = KeyPressMask | ExposureMask; default_root = XDefaultRootWindow(display); win = XCreateWindow(display, default_root, 0, 0, 800, 800, 0, CopyFromParent, InputOutput, CopyFromParent, CWBackPixel | CWEventMask, &attributes); font = XLoadQueryFont(display, "8x16"); smallfont = XLoadQueryFont(display, "7x13"); vals.foreground = black; vals.background = white; vals.font = font -> fid; gc = XCreateGC(display, win, GCForeground | GCBackground | GCFont, &vals); vals.font = smallfont -> fid; smallgc = XCreateGC(display, win, GCForeground | GCBackground | GCFont, &vals); XMapWindow(display, win); } void rectangle(int x, int y, int width, int height) { XDrawRectangle(display, win, gc, x, y, width, height); } void string(int x, int y, char *contents) { int len = strlen(contents); int w = XTextWidth(font, contents, len); XDrawImageString(display, win, gc, x - w / 2, y + 8, contents, len); } void smallstring(int x, int y, char *contents) { int len = strlen(contents); XDrawImageString(display, win, smallgc, x, y, contents, len); } void mop(int x, int y, char *label) { XDrawArc(display, win, gc, x - 15, y - 15, 30, 30, 0, 360 * 64); string(x, y, label); } void registr(int x, int y, int w, int h, char *label) { rectangle(x, y, w, h); string(x + w / 2, y + h / 2, label); } void line(int x1, int y1, int x2, int y2) { XDrawLine(display, win, gc, x1, y1, x2, y2); } void vline(int x, int y, int y1) { line(x, y, x, y1); } void hline(int x, int y, int x1) { line(x, y, x1, y); } /* half of the thickness of a thick wire */ #define HT 4 void uparrow(int x, int y) { int delta = 2 * HT; line(x, y, x - delta, y + delta); line(x, y, x + delta, y + delta); } void downarrow(int x, int y) { int delta = 2 * HT; line(x, y, x - delta, y - delta); line(x, y, x + delta, y - delta); } void leftarrow(int x, int y) { int delta = 2 * HT; line(x, y, x + delta, y - delta); line(x, y, x + delta, y + delta); } void rightarrow(int x, int y) { int delta = 2 * HT; line(x, y, x - delta, y - delta); line(x, y, x - delta, y + delta); } void thick_hwire(int x, int y, int x1) { if(x1 < x) { hline(x - HT, y - HT, x1 + HT); hline(x - HT, y + HT, x1 + HT); } else { hline(x + HT, y - HT, x1 - HT); hline(x + HT, y + HT, x1 - HT); } } void thick_vwire(int x, int y, int y1) { if(y1 < y) { vline(x - HT, y - HT, y1 + HT); vline(x + HT, y - HT, y1 + HT); } else { vline(x - HT, y + HT, y1 - HT); vline(x + HT, y + HT, y1 - HT); } } void ulcorner(int x, int y) { vline(x - HT, y - HT, y + HT); hline(x - HT, y - HT, x + HT); } void urcorner(int x, int y) { vline(x + HT, y - HT, y + HT); hline(x + HT, y - HT, x - HT); } void llcorner(int x, int y) { vline(x - HT, y + HT, y - HT); hline(x - HT, y + HT, x + HT); } void lrcorner(int x, int y) { vline(x + HT, y + HT, y - HT); hline(x + HT, y + HT, x - HT); } void upline(int x, int y1, int y2) { XPoint points[3]; XDrawLine(display, win, gc, x, y1, x, y2); points[0].x = x + 0; points[0].y = y2; points[1].x = x - 3; points[1].y = y2 + 7; points[2].x = x + 3; points[2].y = y2 + 7; XFillPolygon(display, win, gc, points, 3, Convex, CoordModeOrigin); } void downline(int x, int y1, int y2) { XPoint points[3]; XDrawLine(display, win, gc, x, y1, x, y2); points[0].x = x + 0; points[0].y = y2; points[1].x = x - 3; points[1].y = y2 - 7; points[2].x = x + 3; points[2].y = y2 - 7; XFillPolygon(display, win, gc, points, 3, Convex, CoordModeOrigin); } void leftline(int x1, int y, int x2) { XPoint points[3]; XDrawLine(display, win, gc, x1, y, x2, y); points[0].x = x2 + 0; points[0].y = y; points[1].x = x2 + 7; points[1].y = y - 3; points[2].x = x2 + 7; points[2].y = y + 3; XFillPolygon(display, win, gc, points, 3, Convex, CoordModeOrigin); } void rightline(int x1, int y, int x2) { XPoint points[3]; XDrawLine(display, win, gc, x1, y, x2, y); points[0].x = x2 + 0; points[0].y = y; points[1].x = x2 - 7; points[1].y = y - 3; points[2].x = x2 - 7; points[2].y = y + 3; XFillPolygon(display, win, gc, points, 3, Convex, CoordModeOrigin); } /* registers */ unsigned char contents_micro_pc_master = 0; unsigned char contents_micro_pc_slave = 0; unsigned char contents_address_reg_master = 0; unsigned char contents_address_reg_slave = 0; unsigned char contents_r0_master = 0; unsigned char contents_r0_slave = 0; unsigned char contents_r1_master = 0; unsigned char contents_r1_slave = 0; unsigned char contents_pc_master = 0; unsigned char contents_pc_slave = 0; /* other important variables */ unsigned char value_address_bus; unsigned char value_data_bus; unsigned char value_alu; /* contents of memories */ unsigned short contents_micro_mem[64] = { 0x00ac, 0x0002, 0x08aa, 0x02a8, 0x0c0a, 0x02a8, 0x0500, 0x0510, 0x0518, 0x0510, 0x0502, 0x1002, 0x9002, 0x5002, 0xd002, 0x3002, 0xb002, 0x7002, 0xf002, 0x02a8, 0x0442, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }; unsigned char contents_main_mem[256] = { 0x01, 0xf3, 0x04, 0x02, 0x0a, 0x07, 0x03, 0x0b, 0x0c, 0x08, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; unsigned char contents_instruction_decoder[32] = { 0x01, 0x02, 0x03, 0x05, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x15, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }; unsigned char mops[16]; char *hex[256] = { "00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "0a", "0b", "0c", "0d", "0e", "0f", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "1a", "1b", "1c", "1d", "1e", "1f", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "2a", "2b", "2c", "2d", "2e", "2f", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "3a", "3b", "3c", "3d", "3e", "3f", "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "4a", "4b", "4c", "4d", "4e", "4f", "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "5a", "5b", "5c", "5d", "5e", "5f", "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "6a", "6b", "6c", "6d", "6e", "6f", "70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "7a", "7b", "7c", "7d", "7e", "7f", "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "8a", "8b", "8c", "8d", "8e", "8f", "90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "9a", "9b", "9c", "9d", "9e", "9f", "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9", "aa", "ab", "ac", "ad", "ae", "af", "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7", "b8", "b9", "ba", "bb", "bc", "bd", "be", "bf", "c0", "c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8", "c9", "ca", "cb", "cc", "cd", "ce", "cf", "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "da", "db", "dc", "dd", "de", "df", "e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9", "ea", "eb", "ec", "ed", "ee", "ef", "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "fa", "fb", "fc", "fd", "fe", "ff", }; /* bus positions */ #define DBX 300 #define ABX 650 #define DBY1 30 #define DBY2 550 #define ABY1 30 #define ABY2 400 void buses(void) { /* data bus */ thick_vwire(DBX, DBY1, DBY2); uparrow(DBX, DBY1); downarrow(DBX, DBY2); string(DBX, DBY1 - 11, "Data Bus"); /* address bus */ thick_vwire(ABX, ABY1, ABY2); uparrow(ABX, ABY1); downarrow(ABX, ABY2); string(ABX, ABY1 - 11, "Address Bus"); } void instruction_decoder(void) { rectangle(180, 100, 80, 400); string(220, 100 - 27, "Instruction"); string(220, 100 - 11, "Decoder"); thick_hwire(DBX, 115, 260); smallstring(DBX - 20, 115 + 20, hex[value_data_bus & 0x1f]); leftarrow(260, 115); thick_hwire(180 + HT, 115, 140); smallstring(180 - 20, 115 + 20, hex[contents_instruction_decoder[value_data_bus & 0x1f]]); leftarrow(140, 115); /* draw contents */ { int x = 180 + 10; int row; for(row = 0; row < 32; row++) { int y = 100 + 12 * row + 20; smallstring(x, y, hex[row]); smallstring(x + 20, y, ":"); smallstring(x + 30, y, hex[contents_instruction_decoder[row]]); } } } void micro_pc(void) { registr(20, 100, 120, 30, "Micro PC"); thick_vwire(80, 130 - HT, 160); smallstring(80 + 15, 130 + 20, hex[contents_micro_pc_slave]); mop(110, 60, "2"); downline(110, 75, 100); smallstring(98, 98, mops[2] ? "1" : "0"); mop(50, 60, "1"); downline(50, 75, 100); smallstring(57, 98, mops[1] ? "1" : "0"); smallstring(120, 98, "ld"); smallstring(25, 98, "clr"); } void micro_mem(void) { rectangle(20, 160, 120, 400); string(80, 160 + 9, "Micro Mem"); downarrow(80, 160); mop(40, 615, "1"); mop(120, 615, "15"); XFillArc(display, win, gc, 66, 615, 4, 4, 0, 360 * 64); XFillArc(display, win, gc, 80, 615, 4, 4, 0, 360 * 64); XFillArc(display, win, gc, 95, 615, 4, 4, 0, 360 * 64); downline(40, 560, 600); downline(120, 560, 600); /* display contents */ { int row; for(row = 0; row < 50; row++) { int y = 160 + 7 * row + 25; int col; for(col = 0; col < 15; col++) { int x = 20 + 7 * col + 5; if(contents_micro_mem[row] & (1 << (col + 1))) vline(x + 2, y, y + 4); else XDrawRectangle(display, win, gc, x, y, 4, 4); } } } } void alu(int x, int y, int w, int h) { int h1 = h / 4; line(x, y, x + h, y + h); hline(x + h, y + h, x + w - h); line(x + w - h, y + h, x + w, y); hline(x + w, y, x + w / 2 + h1); line(x + w / 2 + h1, y, x + w / 2, y + h1); line(x + w / 2, y + h1, x + w / 2 - h1, y); hline(x + w / 2 - h1, y, x); string(x + w / 2, y + h / 2, "ALU"); XDrawArc(display, win, gc, x - 55, y + h / 2 - 15, 30, 30, 90 * 64, 180 * 64); XDrawArc(display, win, gc, x - 35, y + h / 2 - 15, 30, 30, -90 * 64, 180 * 64); hline(x - 40, y + h / 2 - 15, x - 20); hline(x - 40, y + h / 2 + 15, x - 20); string(x - 30, y + h / 2, "13-15"); rightline(x - 5, y + h / 2, x + h / 2); smallstring(x - 2, y + h / 2 + 14, mops[13] ? "1" : "0"); smallstring(x + 5, y + h / 2 + 14, mops[14] ? "1" : "0"); smallstring(x + 12, y + h / 2 + 14, mops[15] ? "1" : "0"); } void alu_and_registrs(int x, int y, int w, int h) { int reg_width = w / 2 - h / 8; int reg_height = h / 3; alu(x, y + 2 * h / 3, w, h / 3); registr(x, y, reg_width, reg_height, "R0"); mop(x - 40, y + reg_height / 2, "11"); rightline(x - 25, y + reg_height / 2, x); smallstring(x - 10, y + reg_height / 2 + 14, mops[11] ? "1" : "0"); registr(x + w - reg_width, y, reg_width, reg_height, "R1"); mop(x + w + 40, y + reg_height / 2, "12"); leftline(x + w + 25, y + reg_height / 2, x + w); smallstring(x + w + 4, y + reg_height / 2 + 14, mops[12] ? "1" : "0"); /* draw the connections from registers to ALU */ thick_vwire(x + reg_width / 2, y + reg_height - HT, y + 2 * h / 3); downarrow(x + reg_width / 2, y + 2 * h / 3); smallstring(x + reg_width / 2 + 10, y + reg_height + 15, hex[contents_r0_slave]); thick_vwire(x + w - reg_width / 2, y + reg_height - HT, y + 2 * h / 3); downarrow(x + w - reg_width / 2, y + 2 * h / 3); smallstring(x + w - reg_width / 2 + 10, y + reg_height + 15, hex[contents_r1_slave]); /* draw connection from ALU to R1 */ thick_vwire(x + w / 2, y + h - HT, y + h + h / 3); smallstring(x + w / 2 + 15, y + h + 20, hex[value_alu]); llcorner(x + w / 2, y + h + h / 3); thick_hwire(x + w / 2, y + h + h / 3, x + w + w / 2); lrcorner(x + w + w / 2, y + h + h / 3); thick_vwire(x + w + w / 2, y + h + h / 3, y - h / 3); urcorner(x + w + w / 2, y - h / 3); thick_hwire(x + w + w / 2, y - h / 3, x + w - reg_width / 2); ulcorner(x + w - reg_width / 2, y - h / 3); thick_vwire(x + w - reg_width / 2, y - h / 3, y); downarrow(x + w - reg_width / 2, y); smallstring(x + w - reg_width / 2 + 15, y - 10, hex[value_alu]); /* draw connection from data bus to R0 */ thick_hwire(DBX, DBY2 - 20, x + reg_width / 2); smallstring(DBX + 15, DBY2 - 20 + 20, hex[value_data_bus]); urcorner(x + reg_width / 2, DBY2 - 20); thick_vwire(x + reg_width / 2, DBY2 - 20, y); downarrow(x + reg_width / 2, y); /* draw connection from R1 to bus driver */ thick_hwire(x + w - reg_width / 2, y + h / 2, x + w / 2); llcorner(x + w / 2, y + h / 2); thick_vwire(x + w / 2, y + h / 2, DBY2 - 50); urcorner(x + w / 2, DBY2 - 50); thick_hwire(x + w / 2, DBY2 - 50, DBX + 60); leftarrow(DBX + 60, DBY2 - 50); smallstring(DBX + 60 + 15, DBY2 - 50 - 10, hex[contents_r1_slave]); registr(DBX + 30, DBY2 - 65, 30, 30, "BD"); mop(DBX + 45, DBY2 - 100, "8"); downline(DBX + 45, DBY2 - 85, DBY2 - 65); smallstring(DBX + 52, DBY2 - 67, mops[8] ? "1" : "0"); thick_hwire(DBX + 30 + HT, DBY2 - 50, DBX + HT); leftarrow(DBX + HT, DBY2 - 50); smallstring(DBX + 15, DBY2 - 50 - 10, hex[value_data_bus]); } void pc(void) { int ypos = (ABY1 + ABY2) / 2; thick_hwire(ABX, ypos, ABX + 50); rightarrow(ABX + 50, ypos); smallstring(ABX + 50 - 20, ypos + 20, hex[value_address_bus]); registr(ABX + 50, ypos - 15, 80, 30, "PC"); thick_vwire(ABX + 50 + 40, ypos - 15 + HT, ypos - 50); smallstring(ABX + 50 + 40 + 15, ypos - 15 - 10, hex[contents_pc_slave]); urcorner(ABX + 50 + 40, ypos - 50); thick_hwire(ABX + 50 + 40, ypos - 50, ABX + 50 + 10); leftarrow(ABX + 50 + 10, ypos - 50); registr(ABX + 50 - 20, ypos - 50 - 15, 30, 30, "BD"); thick_hwire(ABX + 50 - 20 + HT, ypos - 50, ABX + HT); leftarrow(ABX + HT, ypos - 50); smallstring(ABX + 15, ypos - 50 - 10, hex[value_address_bus]); mop(ABX + 45, ypos - 110, "5"); downline(ABX + 45, ypos - 95, ypos - 65); smallstring(ABX + 52, ypos - 67, mops[5] ? "1" : "0"); mop(ABX + 70, ypos + 55, "6"); upline(ABX + 70, ypos + 40, ypos + 15); smallstring(ABX + 75, ypos + 27, mops[6] ? "1" : "0"); smallstring(ABX + 50, ypos + 28, "ld"); mop(ABX + 110, ypos + 55, "7"); upline(ABX + 110, ypos + 40, ypos + 15); smallstring(ABX + 98, ypos + 27, mops[7] ? "1" : "0"); smallstring(ABX + 115, ypos + 28, "incr"); } void address_reg(void) { int dx = (ABX - DBX - 30) / 6; int ypos = ABY2 - 30; thick_hwire(DBX, ypos, DBX + dx); rightarrow(DBX + dx, ypos); smallstring(DBX + dx - 20, ypos + 20, hex[value_data_bus]); registr(DBX + dx, ypos - 15, 3 * dx, 30, "Address Reg"); mop(DBX + 3 * dx, ypos + 50, "9"); upline(DBX + 3 * dx, ypos + 35, ypos + 15); smallstring(DBX + 3 * dx + 7, ypos + 27, mops[9] ? "1" : "0"); thick_hwire(DBX + 4 * dx - HT, ypos, DBX + 5 * dx); rightarrow(DBX + 5 * dx, ypos); smallstring(DBX + 5 * dx - 20, ypos + 20, hex[contents_address_reg_slave]); registr(DBX + 5 * dx, ypos - 15, 30, 30, "BD"); mop(DBX + 5 * dx + 15, ypos + 50, "10"); upline(DBX + 5 * dx + 15, ypos + 35, ypos + 15); smallstring(DBX + 5 * dx + 3, ypos + 27, mops[10] ? "1" : "0"); thick_hwire(DBX + 5 * dx + 30, ypos, ABX - HT); rightarrow(ABX - HT, ypos); smallstring(ABX - HT - 20, ypos + 20, hex[value_address_bus]); } void main_mem(void) { int xpos = DBX + 30; int ypos = DBY1; int w = ABX - 30 - xpos; int h = ABY2 - ABY1 - 100; registr(xpos, ypos, w, h, ""); thick_hwire(DBX + HT, ypos + h / 2, xpos); leftarrow(DBX + HT, ypos + h / 2); smallstring(DBX + HT + 5, ypos + h / 2 + 20, hex[value_data_bus]); rightarrow(xpos, ypos + h / 2); thick_hwire(xpos + w, ypos + h / 2, ABX); leftarrow(xpos + w, ypos + h / 2); smallstring(xpos + w + 5, ypos + h / 2 + 20, hex[value_address_bus]); string(xpos + w / 2, ypos - 11, "Main Memory"); mop(xpos + 50, ypos + h + 30, "3"); upline(xpos + 50, ypos + h + 15, ypos + h); smallstring(xpos + 57, ypos + h + 12, mops[3] ? "1" : "0"); smallstring(xpos + 30, ypos + h + 15, "en"); mop(xpos + w - 50, ypos + h + 30, "4"); upline(xpos + w - 50, ypos + h + 15, ypos + h); smallstring(xpos + w - 62, ypos + h + 12, mops[4] ? "1" : "0"); smallstring(xpos + w - 40, ypos + h + 15, "r/w"); /* display contents */ { int col; for(col = 0; col < 16; col++) { int row; for(row = 0; row < 16; row++) { int x = xpos + 2 + w / 16 * col; int y = ypos + 20 + row * 16; smallstring(x, y, hex[contents_main_mem[col * 16 + row]]); } } } } void evaluate_combinatorial(void) { unsigned short allmops = contents_micro_mem[contents_micro_pc_slave]; int i; for(i = 0; i < 16; i++) mops[i] = (allmops >> i) & 1; /* figure out what the address bus is */ if(mops[5]) value_address_bus = contents_pc_slave; else if(mops[10]) value_address_bus = contents_address_reg_slave; else value_address_bus = 0; /* possibly propagate address bus to PC */ if(mops[6]) contents_pc_master = value_address_bus; else if(mops[7]) contents_pc_master = contents_pc_slave + 1; /* figure out what the data bus is */ if(mops[3] && !mops[4]) value_data_bus = contents_main_mem[value_address_bus]; else if(mops[8]) value_data_bus = contents_r1_slave; /* figure out whether we should write memory */ if(mops[3] && mops[4]) contents_main_mem[value_address_bus] = value_data_bus; /* propagate data bus */ if(mops[1]) contents_micro_pc_master = 0; else if(mops[2]) contents_micro_pc_master = contents_instruction_decoder[value_data_bus & 0x1f]; else contents_micro_pc_master = (contents_micro_pc_slave + 1) & 0x3f; if(mops[9]) contents_address_reg_master = value_data_bus; if(mops[11]) contents_r0_master = value_data_bus; /* figure out the value of the alu */ switch((mops[13] << 2) | (mops[14] << 1) | (mops[15] << 0)) { case 0: value_alu = contents_r0_slave; break; case 1: value_alu = contents_r1_slave << 1; break; case 2: value_alu = contents_r1_slave >> 1; break; case 3: value_alu = contents_r0_slave + contents_r1_slave; break; case 4: value_alu = contents_r0_slave - contents_r1_slave; break; case 5: value_alu = contents_r0_slave & contents_r1_slave; break; case 6: value_alu = contents_r0_slave | contents_r1_slave; break; case 7: value_alu = ~contents_r0_slave; break; } /* possibly propagate alu to r1 */ if(mops[12]) contents_r1_master = value_alu; } void evaluate_sequential(void) { contents_r0_slave = contents_r0_master; contents_r1_slave = contents_r1_master; contents_pc_slave = contents_pc_master; contents_micro_pc_slave = contents_micro_pc_master; contents_address_reg_slave = contents_address_reg_master; } void expose_handler(void) { micro_pc(); micro_mem(); instruction_decoder(); buses(); alu_and_registrs(DBX, DBY2 + 20, 300, 100); pc(); address_reg(); main_mem(); XFlush(display); } int char_to_number(char c) { return (c >= '0' && c <= '9') ? c - '0' : c - 'a' + 10; } void read_micro_memory(char *micro_memory) { FILE *infile = fopen(micro_memory, "r"); int i; if(infile == NULL) { fprintf(stderr, "can't open micro memory file %s\n", micro_memory); exit(EXIT_FAILURE); } for(i = 0; i < 64; i++) { unsigned short word = 0; int j; for(j = 1; j <= 15; j++) { if(getc(infile) == '1') word |= (1 << j); } contents_micro_mem[i] = word; /* skip until end of line */ while(getc(infile) != '\n') ; } fclose(infile); } void read_instruction_decoder(char *instruction_decoder) { FILE *infile = fopen(instruction_decoder, "r"); int i; if(infile == NULL) { fprintf(stderr, "can't open instruction decoder file %s\n", instruction_decoder); exit(EXIT_FAILURE); } for(i = 0; i < 32; i++) { int num = char_to_number(getc(infile)); num = num * 16 + char_to_number(getc(infile)); contents_instruction_decoder[i] = num & 0x3f; /* skip until end of line */ while(getc(infile) != '\n') ; } fclose(infile); } void read_main_memory(char *main_memory) { FILE *infile = fopen(main_memory, "r"); int i; if(infile == NULL) { fprintf(stderr, "can't open main memory file %s\n", main_memory); exit(EXIT_FAILURE); } for(i = 0; i < 256; i++) { int num = char_to_number(getc(infile)); num = num * 16 + char_to_number(getc(infile)); contents_main_mem[i] = num; /* skip until end of line */ while(getc(infile) != '\n') ; } fclose(infile); } void event_loop(void) { XEvent event; while(1) { XNextEvent(display, &event); switch(event.type) { case KeyPress: evaluate_sequential(); evaluate_combinatorial(); expose_handler(); break; case Expose: expose_handler(); break; } } } void usage(void) { fprintf(stderr, "Usage: simulator [options]\n"); fprintf(stderr, " options:\n"); fprintf(stderr, " --main-memory file\n"); fprintf(stderr, " -M file\n"); fprintf(stderr, " take contents of main memory from file\n"); fprintf(stderr, " --micro-memory file\n"); fprintf(stderr, " -m file\n"); fprintf(stderr, " take contents of micro memory from file\n"); fprintf(stderr, " --instruction-decoder file\n"); fprintf(stderr, " -i file\n"); fprintf(stderr, " take contents of instruction decoder from file\n"); } int main(int argc, char *argv[]) { char *instruction_decoder = 0; char *micro_memory = 0; char *main_memory = 0; while(1) { static struct option long_options[] = { {"help", 0, 0, 'h'}, {"instruction-decoder", 1, 0, 'i'}, {"micro-memory", 1, 0, 'm'}, {"main-memory", 1, 0, 'M'}, {0, 0, 0, 0} }; int option_index = 0; int c = getopt_long(argc, argv, "hi:m:M:", long_options, &option_index); if(c == -1) break; switch(c) { case 'h': usage(); exit(EXIT_SUCCESS); break; case 'i': instruction_decoder = strdup(optarg); break; case 'm': micro_memory = strdup(optarg); break; case 'M': main_memory = strdup(optarg); break; case '?': exit(EXIT_FAILURE); break; } } if(optind < argc) { while(optind < argc) fprintf(stderr, "unknown argument: %s\n", argv[optind++]); exit(EXIT_FAILURE); } if(instruction_decoder) read_instruction_decoder(instruction_decoder); if(main_memory) read_main_memory(main_memory); if(micro_memory) read_micro_memory(micro_memory); create_main_window(); XFlush(display); evaluate_combinatorial(); expose_handler(); event_loop(); return EXIT_SUCCESS; }