#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) { display = XOpenDisplay(NULL); screen_number = XDefaultScreen(display); screen = XScreenOfDisplay(display, screen_number); black = XBlackPixelOfScreen(screen); white = XWhitePixelOfScreen(screen); default_root = XDefaultRootWindow(display); win = XCreateSimpleWindow(display, default_root, 0, 0, 800, 800, 0, black, white); 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); XDrawString(display, win, gc, x - w / 2, y + 8, contents, len); } void smallstring(int x, int y, char *contents) { int len = strlen(contents); XDrawString(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); } 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 600 #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 - 9, "Data Bus"); /* address bus */ thick_vwire(ABX, ABY1, ABY2); uparrow(ABX, ABY1); downarrow(ABX, ABY2); string(ABX, ABY1 - 9, "Address Bus"); } void instruction_decoder(void) { rectangle(180, 100, 80, 400); string(220, 100 - 25, "Instruction"); string(220, 100 - 9, "Decoder"); thick_hwire(DBX, 115, 260); leftarrow(260, 115); thick_hwire(180 + HT, 115, 140); leftarrow(140, 115); } void micro_pc(void) { registr(20, 100, 120, 30, "Micro PC"); thick_vwire(80, 130 - HT, 160); mop(110, 60, "2"); downline(110, 75, 100); mop(50, 60, "1"); downline(50, 75, 100); 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, "16"); 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); } 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-16"); } 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); 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); /* draw the connections from registrs 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); 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); /* draw connection from ALU to R1 */ thick_vwire(x + w / 2, y + h - HT, y + h + h / 3); 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); /* draw connection from data bus to R0 */ thick_hwire(DBX, DBY2 - 20, x + reg_width / 2); 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); registr(DBX + 30, DBY2 - 65, 30, 30, "BD"); mop(DBX + 45, DBY2 - 100, "8"); downline(DBX + 45, DBY2 - 85, DBY2 - 65); thick_hwire(DBX + 30 + HT, DBY2 - 50, DBX + HT); leftarrow(DBX + HT, DBY2 - 50); } void pc(void) { int ypos = (ABY1 + ABY2) / 2; thick_hwire(ABX, ypos, ABX + 50); rightarrow(ABX + 50, ypos); registr(ABX + 50, ypos - 15, 80, 30, "PC"); thick_vwire(ABX + 50 + 40, ypos - 15 + HT, ypos - 50); 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); mop(ABX + 45, ypos - 110, "5"); downline(ABX + 45, ypos - 95, ypos - 65); mop(ABX + 70, ypos + 55, "6"); upline(ABX + 70, ypos + 40, ypos + 15); smallstring(ABX + 50, ypos + 28, "ld"); mop(ABX + 110, ypos + 55, "7"); upline(ABX + 110, ypos + 40, ypos + 15); smallstring(ABX + 115, ypos + 28, "incr"); } void address_reg(void) { int dx = (ABX - DBX - 30) / 6; int ypos = ABY2 - 30; thick_hwire(DBX + HT, ypos, DBX + dx); rightarrow(DBX + dx, ypos); 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); thick_hwire(DBX + 4 * dx - HT, ypos, DBX + 5 * dx); rightarrow(DBX + 5 * dx, ypos); 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); thick_hwire(DBX + 5 * dx + 30, ypos, ABX - HT); rightarrow(ABX - HT, ypos); } 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); rightarrow(xpos, ypos + h / 2); thick_hwire(xpos + w, ypos + h / 2, ABX); leftarrow(xpos + w, ypos + h / 2); string(xpos + w / 2, ypos - 9, "Main Memory"); mop(xpos + 50, ypos + h + 30, "3"); upline(xpos + 50, ypos + h + 15, ypos + h); 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 - 40, ypos + h + 15, "r/w"); } /* 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[256]; unsigned char contents_main_mem[256]; unsigned char contents_instruction_decoder[256]; unsigned char mops[16]; 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; /* 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(mop[6]) contents_pc_master = value_address_bus; else if(mop[5]) contents_pc_master = contents_pc_slave + 1; /* figure out what the data bus is */ if(mop[3] && !mop[4]) value_data_bus = contents_main_mem[value_address_bus]; else if(mop[8]) value_data_bus = contents_r1_slave[value_address_bus]; /* figure out whether we should write memory */ if(mop[3] && mop[4]) contents_main_mem[value_address_bus] = value_data_bus; /* propagate data bus */ if(!mop[1] && mop[2]) contents_micro_pc_master = contents_instruction_decoder[value_data_bus]; if(mop[9]) contents_address_reg_master = value_data_bus; if(mop[11]) contents_r0_master = value_data_bus; /* figure out the value of the alu */ switch((mop[13] << 2) | (mop[14] << 1) | (mop[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 + contens_r1_slave; break; case 4: value_alu = contents_r0_slave - contens_r1_slave; break; } /* possibly propagate alu to r1 */ if(mop[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; } 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 main(int argc, char *argv[]) { create_main_window(); XFlush(display); sleep(5); expose_handler(); sleep(100); return EXIT_SUCCESS; }