00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00301 #include "StdAfx.h"
00302 #include "System.h"
00303 #include "AlphaCPU.h"
00304 #include "lockstep.h"
00305 #include "DPR.h"
00306
00307 #include <ctype.h>
00308 #include <stdlib.h>
00309 #include <signal.h>
00310
00311 #define CLOCK_RATIO 10000
00312
00313 #if defined(LS_MASTER) || defined(LS_SLAVE)
00314 char debug_string[10000] = "";
00315 char* dbg_strptr = debug_string;
00316 #endif
00317
00321 CSystem::CSystem(CConfigurator* cfg)
00322 {
00323 int i;
00324
00325 if(theSystem != 0)
00326 FAILURE(Configuration, "More than one system");
00327 theSystem = this;
00328 myCfg = cfg;
00329
00330 iNumComponents = 0;
00331 iNumMemories = 0;
00332 iNumCPUs = 0;
00333 iNumMemoryBits = (int) myCfg->get_num_value("memory.bits", false, 27);
00334
00335
00336 #if defined(IDB)
00337 iSingleStep = 0;
00338 iSSCycles = 0;
00339 #endif
00340 for(i = 0; i < 4; i++)
00341 state.cchip.dim[i] = 0;
00342 state.cchip.drir = 0;
00343 state.cchip.misc = U64(0x0000000800000000);
00344 state.cchip.csc = U64(0x3142444014157803);
00345
00346 state.dchip.drev = 0x01;
00347 state.dchip.dsc = 0x43;
00348 state.dchip.dsc2 = 0x03;
00349 state.dchip.str = 0x25;
00350
00351
00352 for(i = 0; i < 2; i++)
00353 {
00354 memset(&state.pchip[i], 0, sizeof(struct SSys_state::SSys_pchip));
00355 state.pchip[i].wsba[3] = 2;
00356 }
00357
00358 state.pchip[0].pctl = U64(0x0000104401440081);
00359 state.pchip[1].pctl = U64(0x0000504401440081);
00360
00361 state.tig.FwWrite = 0;
00362 state.tig.HaltA = 0;
00363 state.tig.HaltB = 0;
00364
00365 if(iNumMemoryBits > 30)
00366 {
00367
00368
00369
00370
00371 CHECK_ALLOCATION(memory = calloc(1 << (iNumMemoryBits - 10), 1 << 10));
00372 }
00373 else
00374 CHECK_ALLOCATION(memory = calloc(1 << iNumMemoryBits, 1));
00375
00376 cpu_lock_mutex = new CFastMutex("cpu-locking-lock");
00377
00378 printf("%s(%s): $Id: System.cpp,v 1.75 2008/03/26 19:16:33 iamcamiel Exp $\n",
00379 cfg->get_myName(), cfg->get_myValue());
00380 }
00381
00386 CSystem::~CSystem()
00387 {
00388 int i;
00389
00390 printf("Freeing memory in use by system...\n");
00391
00392 for(i = 0; i < iNumComponents; i++)
00393 delete acComponents[i];
00394
00395 for(i = 0; i < iNumMemories; i++)
00396 free(asMemories[i]);
00397
00398 free(memory);
00399 }
00400
00404 void CSystem::ResetMem(unsigned int membits)
00405 {
00406 free(memory);
00407 iNumMemoryBits = membits;
00408 CHECK_ALLOCATION(memory = calloc(1 << iNumMemoryBits, 1));
00409 }
00410
00414 int CSystem::RegisterComponent(CSystemComponent* component)
00415 {
00416 acComponents[iNumComponents] = component;
00417 iNumComponents++;
00418 return 0;
00419 }
00420
00425 unsigned int CSystem::get_memory_bits()
00426 {
00427 return iNumMemoryBits;
00428 }
00429
00433 char* CSystem::PtrToMem(u64 address)
00434 {
00435 if(address >> iNumMemoryBits)
00436 return 0;
00437
00438 return &(((char*) memory)[(int) address]);
00439 }
00440
00444 int CSystem::RegisterCPU(class CAlphaCPU* cpu)
00445 {
00446 if(iNumCPUs >= 4)
00447 return -1;
00448 acCPUs[iNumCPUs] = cpu;
00449 iNumCPUs++;
00450 return iNumCPUs - 1;
00451 }
00452
00456 int CSystem::RegisterMemory(CSystemComponent* component, int index, u64 base,
00457 u64 length)
00458 {
00459 struct SMemoryUser* m;
00460 int i;
00461 for(i = 0; i < iNumMemories; i++)
00462 {
00463 if((asMemories[i]->component == component) && (asMemories[i]->index == index))
00464 {
00465 asMemories[i]->base = base;
00466 asMemories[i]->length = length;
00467 return 0;
00468 }
00469 }
00470
00471 CHECK_ALLOCATION(m = (struct SMemoryUser*) malloc(sizeof(struct SMemoryUser)));
00472 m->component = component;
00473 m->base = base;
00474 m->length = length;
00475 m->index = index;
00476
00477 asMemories[iNumMemories] = m;
00478 iNumMemories++;
00479 return 0;
00480 }
00481
00482 int got_sigint = 0;
00483
00487 void sigint_handler(int signum)
00488 {
00489 got_sigint = 1;
00490 }
00491
00495 void CSystem::Run()
00496 {
00497 int i;
00498
00499 int k;
00500
00501
00502 signal(SIGINT, &sigint_handler);
00503
00504 start_threads();
00505
00506 for(k = 0;; k++)
00507 {
00508 if(got_sigint)
00509 FAILURE(Graceful, "CTRL-C detected");
00510 Poco::Thread::sleep(100);
00511 for(i = 0; i < iNumComponents; i++)
00512 acComponents[i]->check_state();
00513 #if !defined(HIDE_COUNTER)
00514 #if defined(PROFILE)
00515 printf("%d | %016"LL "x | %"LL "d profiled instructions. \r", k,
00516 acCPUs[0]->get_pc(), profiled_insts);
00517 #else
00518 printf("%d | %016"LL "x\r", k, acCPUs[0]->get_pc());
00519 #endif
00520 #endif
00521 }
00522
00523
00524
00525 }
00526
00531 int CSystem::SingleStep()
00532 {
00533 int i;
00534 int result;
00535
00536 for(i = 0; i < iNumCPUs; i++)
00537 acCPUs[i]->execute();
00538
00539
00540 #if defined(LS_MASTER) || defined(LS_SLAVE)
00541 if(!(iSingleStep % 50))
00542 {
00543 lockstep_sync_m2s("sync1");
00544 *dbg_strptr = '\0';
00545 lockstep_compare(debug_string);
00546 dbg_strptr = debug_string;
00547 *dbg_strptr = '\0';
00548 }
00549 #endif
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568 return 0;
00569 }
00570
00571 #ifdef DEBUG_PORTACCESS
00572 u64 lastport;
00573 #endif
00574 void CSystem::cpu_lock(int cpuid, u64 address)
00575 {
00576 SCOPED_FM_LOCK(cpu_lock_mutex);
00577
00578
00579 state.cpu_lock_flags |= (1 << cpuid);
00580 state.cpu_lock_address[cpuid] = address;
00581 }
00582
00583 bool CSystem::cpu_unlock(int cpuid)
00584 {
00585 SCOPED_FM_LOCK(cpu_lock_mutex);
00586
00587 bool retval;
00588 retval = state.cpu_lock_flags & (1 << cpuid);
00589
00590
00591 state.cpu_lock_flags &= ~(1 << cpuid);
00592 return retval;
00593 }
00594
00595 void CSystem::cpu_break_lock(int cpuid, CSystemComponent* source)
00596 {
00597 SCOPED_FM_LOCK(cpu_lock_mutex);
00598 printf("cpu%d: lock broken by %s. \n", cpuid, source->devid_string);
00599 state.cpu_lock_flags &= ~(1 << cpuid);
00600 }
00601
00684 void CSystem::WriteMem(u64 address, int dsize, u64 data, CSystemComponent* source)
00685 {
00686 u64 a;
00687 int i;
00688 u8* p;
00689 #if defined(ALIGN_MEM_ACCESS)
00690 u64 t64;
00691 u32 t32;
00692 u16 t16;
00693 #endif
00694 if(state.cpu_lock_flags)
00695 {
00696 for(i = 0; i < iNumCPUs; i++)
00697 {
00698 if((state.cpu_lock_flags & (1 << i)) && (
00699 !((state.cpu_lock_address[i] ^ address) & U64(0x00000807ffffff00)))
00700 && (source != acCPUs[i])) cpu_break_lock(i, source);
00701 }
00702 }
00703
00704 a = address & U64(0x00000807ffffffff);
00705
00706 if(a >> iNumMemoryBits)
00707 {
00708
00709
00710 for(i = 0; i < iNumMemories; i++)
00711 {
00712 if((a >= asMemories[i]->base)
00713 && (a < asMemories[i]->base + asMemories[i]->length))
00714 {
00715 asMemories[i]->component->WriteMem(asMemories[i]->index,
00716 a - asMemories[i]->base, dsize, data);
00717 return;
00718 }
00719 }
00720
00721 if((a == U64(0x00000801FC000CF8)) && (dsize == 32))
00722 {
00723 state.cf8_address[0] = (u32) data & 0x00ffffff;
00724 return;
00725 }
00726
00727 if((a == U64(0x00000803FC000CF8)) && (dsize == 32))
00728 {
00729 state.cf8_address[1] = (u32) data & 0x00ffffff;
00730 return;
00731 }
00732
00733 if((a == U64(0x00000801FC000CFC)) && (dsize == 32))
00734 {
00735 printf("PCI 0 config space write through CF8/CFC mechanism. \n");
00736 getc(stdin);
00737 WriteMem(U64(0x00000801FE000000) | state.cf8_address[0], dsize, data,
00738 source);
00739 return;
00740 }
00741
00742 if((a == U64(0x00000803FC000CFC)) && (dsize == 32))
00743 {
00744 printf("PCI 1 config space write through CF8/CFC mechanism. \n");
00745 getc(stdin);
00746 WriteMem(U64(0x00000803FE000000) | state.cf8_address[1], dsize, data,
00747 source);
00748 return;
00749 }
00750
00751 if(a >= U64(0x00000801A0000000) && a <= U64(0x00000801AFFFFFFF))
00752 {
00753 cchip_csr_write((u32) a & 0xFFFFFFF, data, source);
00754 return;
00755 }
00756
00757 if(a >= U64(0x0000080180000000) && a <= U64(0x000008018FFFFFFF))
00758 {
00759 pchip_csr_write(0, (u32) a & 0xFFFFFFF, data);
00760 return;
00761 }
00762
00763 if(a >= U64(0x0000080380000000) && a <= U64(0x000008038FFFFFFF))
00764 {
00765 pchip_csr_write(1, (u32) a & 0xFFFFFFF, data);
00766 return;
00767 }
00768
00769 if(a >= U64(0x00000801B0000000) && a <= U64(0x00000801BFFFFFFF))
00770 {
00771 dchip_csr_write((u32) a & 0xFFFFFFF, (u8) data & 0xff);
00772 return;
00773 }
00774
00775 if(a >= U64(0x0000080100000000) && a <= U64(0x000008013FFFFFFF))
00776 {
00777 tig_write((u32) a & 0x3FFFFFFF, (u8) data);
00778 return;
00779 }
00780
00781 if(a >= U64(0x801fc000000) && a < U64(0x801fe000000))
00782 {
00783
00784
00785
00786
00787
00788
00789 return;
00790 }
00791
00792 if(a >= U64(0x803fc000000) && a < U64(0x803fe000000))
00793 {
00794
00795
00796 if(source)
00797 {
00798 printf("Write to unknown IO port %"LL "x on PCI 1 from %s \n",
00799 a & U64(0x1ffffff), source->devid_string);
00800 }
00801 else
00802 printf("Write to unknown IO port %"LL "x on PCI 1 \n",
00803 a & U64(0x1ffffff));
00804 return;
00805 }
00806
00807 if(a >= U64(0x80000000000) && a < U64(0x80100000000))
00808 {
00809
00810
00811 u64 paddr = a & U64(0xffffffff);
00812 if(paddr > 0xb8fff || paddr < 0xb8000)
00813 {
00814 if(source)
00815 {
00816 printf("Write to unknown memory %"LL "x on PCI 0 from %s \n",
00817 a & U64(0xffffffff), source->devid_string);
00818 }
00819 else
00820 printf("Write to unknown memory %"LL "x on PCI 0 \n",
00821 a & U64(0xffffffff));
00822 }
00823 }
00824
00825 if(a >= U64(0x80200000000) && a < U64(0x80300000000))
00826 {
00827
00828
00829 if(source)
00830 {
00831 printf("Write to unknown memory %"LL "x on PCI 1 from %s \n",
00832 a & U64(0xffffffff), source->devid_string);
00833 }
00834 else
00835 printf("Write to unknown memory %"LL "x on PCI 1 \n",
00836 a & U64(0xffffffff));
00837 return;
00838 }
00839
00840 #ifdef DEBUG_UNKMEM
00841 if(source)
00842 printf("Write to unknown memory %"LL "x from %s \n", a,
00843 source->devid_string);
00844 else
00845 printf("Write to unknown memory %"LL "x \n", a);
00846 #endif
00847 return;
00848 }
00849
00850 p = (u8*) memory + a;
00851
00852 switch(dsize)
00853 {
00854 case 8: *((u8*) p) = (u8) data; break;
00855 case 16: *((u16*) p) = endian_16((u16) data); break;
00856 case 32: *((u32*) p) = endian_32((u32) data); break;
00857 default: *((u64*) p) = endian_64((u64) data);
00858 }
00859 }
00860
00943 u64 CSystem::ReadMem(u64 address, int dsize, CSystemComponent* source)
00944 {
00945 u64 a;
00946 int i;
00947 u8* p;
00948
00949 a = address & U64(0x00000807ffffffff);
00950 if(a >> iNumMemoryBits)
00951 {
00952
00953
00954 for(i = 0; i < iNumMemories; i++)
00955 {
00956 if((a >= asMemories[i]->base)
00957 && (a < asMemories[i]->base + asMemories[i]->length))
00958 return asMemories[i]->component->ReadMem(asMemories[i]->index,
00959 a - asMemories[i]->base, dsize);
00960 }
00961
00962 if((a == U64(0x00000801FC000CFC)) && (dsize == 32))
00963 {
00964 printf("PCI 0 config space read through CF8/CFC mechanism. \n");
00965 getc(stdin);
00966 return ReadMem(U64(0x00000801FE000000) | state.cf8_address[0], dsize,
00967 source);
00968 }
00969
00970 if((a == U64(0x00000803FC000CFC)) && (dsize == 32))
00971 {
00972 printf("PCI 1 config space read through CF8/CFC mechanism. \n");
00973 getc(stdin);
00974 return ReadMem(U64(0x00000803FE000000) | state.cf8_address[1], dsize,
00975 source);
00976 }
00977
00978 if(a >= U64(0x00000801A0000000) && a <= U64(0x00000801AFFFFFFF))
00979 return cchip_csr_read((u32) a & 0xFFFFFFF, source);
00980
00981 if(a >= U64(0x0000080180000000) && a <= U64(0x000008018FFFFFFF))
00982 return pchip_csr_read(0, (u32) a & 0xFFFFFFF);
00983
00984 if(a >= U64(0x0000080380000000) && a <= U64(0x000008038FFFFFFF))
00985 return pchip_csr_read(1, (u32) a & 0xFFFFFFF);
00986
00987 if(a >= U64(0x00000801B0000000) && a <= U64(0x00000801BFFFFFFF))
00988 return dchip_csr_read((u32) a & 0xFFFFFFF) * U64(0x0101010101010101);
00989
00990 if(a >= U64(0x0000080100000000) && a <= U64(0x000008013FFFFFFF))
00991 return tig_read((u32) a & 0x3FFFFFFF);
00992
00993 if((a >= U64(0x801fe000000) && a < U64(0x801ff000000))
00994 || (a >= U64(0x803fe000000) && a < U64(0x803ff000000)))
00995 {
00996
00997
00998 switch(dsize)
00999 {
01000 case 8: return X64_BYTE;
01001 case 16: return X64_WORD;
01002 case 32: return X64_LONG;
01003 case 64: return X64_QUAD;
01004 }
01005 }
01006
01007 if(a >= U64(0x800000c0000) && a < U64(0x801000e0000))
01008 {
01009
01010
01011 return 0;
01012 }
01013
01014 if(a >= U64(0x801fc000000) && a < U64(0x801fe000000))
01015 {
01016
01017
01018
01019
01020
01021
01022 return 0;
01023 }
01024
01025 if(a >= U64(0x803fc000000) && a < U64(0x803fe000000))
01026 {
01027
01028
01029 if(source)
01030 {
01031 printf("Read from unknown IO port %"LL "x on PCI 1 from %s \n",
01032 a & U64(0x1ffffff), source->devid_string);
01033 }
01034 else
01035 printf("Read from unknown IO port %"LL "x on PCI 1 \n",
01036 a & U64(0x1ffffff));
01037 return 0;
01038 }
01039
01040 if(a >= U64(0x80000000000) && a < U64(0x80100000000))
01041 {
01042
01043
01044 u64 paddr = a & U64(0xffffffff);
01045 if(paddr > 0xb8fff || paddr < 0xb8000)
01046 {
01047 if(source)
01048 {
01049 printf("Read from unknown memory %"LL "x on PCI 0 from %s \n",
01050 a & U64(0xffffffff), source->devid_string);
01051 }
01052 else
01053 printf("Read from unknown memory %"LL "x on PCI 0 \n",
01054 a & U64(0xffffffff));
01055 }
01056
01057 return 0;
01058 }
01059
01060 if(a >= U64(0x80200000000) && a < U64(0x80300000000))
01061 {
01062
01063
01064 if(source)
01065 {
01066 printf("Read from unknown memory %"LL "x on PCI 1 from %s \n",
01067 a & U64(0xffffffff), source->devid_string);
01068 }
01069 else
01070 printf("Read from unknown memory %"LL "x on PCI 1 \n",
01071 a & U64(0xffffffff));
01072 return 0;
01073 }
01074
01075 #ifdef DEBUG_UNKMEM
01076 if(source)
01077 printf("Read from unknown memory %"LL "x from %s \n", a,
01078 source->devid_string);
01079 else
01080 printf("Read from unknown memory %"LL "x \n", a);
01081 #endif
01082 return 0x00;
01083
01084
01085 }
01086
01087 p = (u8*) memory + a;
01088
01089 switch(dsize)
01090 {
01091 case 8: return *((u8*) p);
01092 case 16: return endian_16(*((u16*) p));
01093 case 32: return endian_32(*((u32*) p));
01094 default: return endian_64(*((u64*) p));
01095 }
01096 }
01097
01464 u64 CSystem::pchip_csr_read(int num, u32 a)
01465 {
01466 switch(a)
01467 {
01468 case 0x000:
01469 case 0x040:
01470 case 0x080:
01471 case 0x0c0:
01472 return state.pchip[num].wsba[(a >> 6) & 3];
01473
01474 case 0x100:
01475 case 0x140:
01476 case 0x180:
01477 case 0x1c0:
01478 return state.pchip[num].wsm[(a >> 6) & 3];
01479
01480 case 0x200:
01481 case 0x240:
01482 case 0x280:
01483 case 0x2c0:
01484 return state.pchip[num].tba[(a >> 6) & 3];
01485
01486 case 0x300:
01487 return state.pchip[num].pctl;
01488
01489 case 0x3c0:
01490 return state.pchip[num].perr;
01491
01492 case 0x400:
01493 return state.pchip[num].perrmask;
01494
01495 case 0x480:
01496 case 0x4c0:
01497 return 0;
01498
01499 case 0x800:
01500 return 0;
01501
01502 default:
01503 printf("Unknown PCHIP %d CSR %07x read attempted.\n", num, a);
01504 return 0;
01505 }
01506 }
01507
01513 void CSystem::pchip_csr_write(int num, u32 a, u64 data)
01514 {
01515 switch(a)
01516 {
01517 case 0x000:
01518 case 0x040:
01519 case 0x080:
01520 state.pchip[num].wsba[(a >> 6) & 3] = data & U64(0x00000000fff00003);
01521 return;
01522
01523 case 0x0c0:
01524 state.pchip[num].wsba[3] = data & U64(0x00000080fff00001) | 2;
01525 return;
01526
01527 case 0x100:
01528 case 0x140:
01529 case 0x180:
01530 case 0x1c0:
01531 state.pchip[num].wsm[(a >> 6) & 3] = data & U64(0x00000000fff00000);
01532 return;
01533
01534 case 0x200:
01535 case 0x240:
01536 case 0x280:
01537 case 0x2c0:
01538 state.pchip[num].tba[(a >> 6) & 3] = data & U64(0x00000007fffffc00);
01539 return;
01540
01541 case 0x300:
01542 state.pchip[num].pctl &= U64(0xffffe300f0300000);
01543 state.pchip[num].pctl |= (data & U64(0x00001cff0fcfffff));
01544 return;
01545
01546 case 0x340:
01547 state.pchip[num].plat = data;
01548 return;
01549
01550 case 0x3c0:
01551 return;
01552
01553 case 0x400:
01554 state.pchip[num].perrmask = data;
01555 return;
01556
01557 case 0x480:
01558 case 0x4c0:
01559 return;
01560
01561 case 0x800:
01562 for(int i = 0; i < iNumComponents; i++)
01563 acComponents[i]->ResetPCI();
01564 return;
01565
01566 default:
01567 printf("Unknown PCHIP %d CSR %07x write with %016"LL "x attempted.\n", num,
01568 a, data);
01569 }
01570 }
01571
01572 u64 CSystem::cchip_csr_read(u32 a, CSystemComponent* source)
01573 {
01574 CAlphaCPU* cpu = (CAlphaCPU*) source;
01575 switch(a)
01576 {
01577 case 0x000:
01578 return state.cchip.csc;
01579
01580 case 0x080:
01581
01582
01583 return state.cchip.misc | ((CAlphaCPU*) source)->get_cpuid();
01584
01585 case 0x100:
01586
01587
01588 return((u64) (iNumMemoryBits - 23) << 12);
01589
01590 case 0x140:
01591 case 0x180:
01592 case 0x1c0:
01593
01594
01595 return 0;
01596
01597 case 0x200:
01598 case 0x240:
01599 case 0x600:
01600 case 0x640:
01601 return state.cchip.dim[((a >> 10) & 2) | ((a >> 6) & 1)];
01602
01603 case 0x280:
01604 case 0x2c0:
01605 case 0x680:
01606 case 0x6c0:
01607 return state.cchip.drir & state.cchip.dim[((a >> 10) & 2) | ((a >> 6) & 1)];
01608
01609 case 0x300:
01610 return state.cchip.drir;
01611
01612 default:
01613 printf("Unknown CCHIP CSR %07x read attempted.\n", a);
01614 return 0;
01615 }
01616 }
01617
01618 void CSystem::cchip_csr_write(u32 a, u64 data, CSystemComponent* source)
01619 {
01620 CAlphaCPU* cpu = (CAlphaCPU*) source;
01621 switch(a)
01622 {
01623 case 0x000:
01624 state.cchip.csc &= ~U64(0x0777777fff3f0000);
01625 state.cchip.csc |= (data & U64(0x0777777fff3f0000));
01626 return;
01627
01628 case 0x080:
01629 state.cchip.misc |= (data & U64(0x00000f0000f00000));
01630 state.cchip.misc &= ~(data & U64(0x0000000010000ff0));
01631 if(data & U64(0x0000000001000000))
01632 {
01633 state.cchip.misc &= ~U64(0x0000000000ff0000);
01634 printf("Arbitration clear from CPU %d (@%"LL "x).\n", cpu->get_cpuid(),
01635 cpu->get_pc() - 4);
01636 }
01637
01638 if(data & U64(0x00000000000f0000))
01639 {
01640 printf("Arbitration %016"LL "x from CPU %d (@%"LL "x)... ", data,
01641 cpu->get_cpuid(), cpu->get_pc() - 4);
01642 if(!(state.cchip.misc & U64(0x00000000000f0000)))
01643 {
01644 state.cchip.misc |= (data & U64(0x00000000000f0000));
01645 printf("won %016"LL "x\n", state.cchip.misc);
01646 }
01647 else
01648 printf("lost %016"LL "x\n", state.cchip.misc);
01649 }
01650
01651
01652 if(data & U64(0x00000000000000f0))
01653 {
01654 for(int i = 0; i < iNumCPUs; i++)
01655 {
01656 if(data & (U64(0x10) << i))
01657 {
01658 acCPUs[i]->irq_h(2, false, 0);
01659
01660
01661 }
01662 }
01663 }
01664
01665
01666 if(data & U64(0x0000000000000f00))
01667 {
01668 for(int i = 0; i < iNumCPUs; i++)
01669 {
01670 if(data & (U64(0x100) << i))
01671 {
01672 acCPUs[i]->irq_h(3, false, 0);
01673 printf("*** IP interrupt cleared for CPU %d from CPU %d(@ %"LL "x).\n",
01674 i, cpu->get_cpuid(), cpu->get_pc() - 4);
01675 }
01676 }
01677 }
01678
01679
01680 if(data & U64(0x000000000000f000))
01681 {
01682 for(int i = 0; i < iNumCPUs; i++)
01683 {
01684 if(data & (U64(0x1000) << i))
01685 {
01686 state.cchip.misc |= U64(0x100) << i;
01687 acCPUs[i]->irq_h(3, true, 0);
01688 printf("*** IP interrupt set for CPU %d from CPU %d(@ %"LL "x)\n", i,
01689 cpu->get_cpuid(), cpu->get_pc() - 4);
01690
01691
01692 }
01693 }
01694 }
01695
01696 return;
01697
01698 case 0x200:
01699 case 0x240:
01700 case 0x600:
01701 case 0x640:
01702 state.cchip.dim[((a >> 10) & 2) | ((a >> 6) & 1)] = data;
01703 return;
01704
01705 default:
01706 printf("Unknown CCHIP CSR %07x write with %016"LL "x attempted.\n", a, data);
01707 }
01708 }
01709
01710 u8 CSystem::dchip_csr_read(u32 a)
01711 {
01712 switch(a)
01713 {
01714 case 0x800:
01715 return state.dchip.dsc;
01716 case 0x840:
01717 return state.dchip.str;
01718 case 0x880:
01719 return state.dchip.drev;
01720 case 0x8c0:
01721 return state.dchip.dsc2;
01722 default: printf("Unknown DCHIP CSR %07x read attempted.\n", a); return 0;
01723 }
01724 }
01725
01726 void CSystem::dchip_csr_write(u32 a, u8 data)
01727 {
01728 printf("Unknown DCHIP CSR %07x write with %02x attempted.\n", a, data);
01729 }
01730
01777 u8 CSystem::tig_read(u32 a)
01778 {
01779 switch(a)
01780 {
01781 case 0x30000000:
01782 return 0;
01783 case 0x30000040:
01784 return state.tig.FwWrite;
01785 case 0x30000100:
01786 return 0;
01787 case 0x300003c0:
01788 return state.tig.HaltA;
01789 case 0x30000480:
01790 return 0;
01791 case 0x300005c0:
01792 return state.tig.HaltB;
01793 case 0x38000180:
01794 return 0xfe;
01795 default: printf("Unknown TIG %08x read attempted.\n", a); return 0;
01796 }
01797 }
01798
01799 void CSystem::tig_write(u32 a, u8 data)
01800 {
01801 switch(a)
01802 {
01803 case 0x30000000:
01804 return;
01805 case 0x30000040:
01806 state.tig.FwWrite = data; return;
01807 case 0x30000100:
01808 printf("Soft reset: %02x\n", data); return;
01809 case 0x300003c0:
01810 state.tig.HaltA = data; return;
01811 case 0x30000480:
01812 return;
01813 case 0x300005c0:
01814 state.tig.HaltB = data; return;
01815 default: printf("Unknown TIG %07x write with %02x attempted.\n", a, data);
01816 }
01817 }
01818
01823 int CSystem::LoadROM()
01824 {
01825 FILE* f;
01826 char* buffer;
01827 int i;
01828 int j;
01829 u64 temp;
01830 u32 scratch;
01831
01832 f = fopen(myCfg->get_text_value("rom.decompressed", "decompressed.rom"), "rb");
01833 if(!f)
01834 {
01835 f = fopen(myCfg->get_text_value("rom.srm", "cl67srmrom.exe"), "rb");
01836 if(!f)
01837 FAILURE(Runtime, "No original or decompressed SRM ROM image found");
01838 printf("%%SYS-I-READROM: Reading original ROM image from %s.\n",
01839 myCfg->get_text_value("rom.srm", "cl67srmrom.exe"));
01840 for(i = 0; i < 0x240; i++)
01841 {
01842 if(feof(f))
01843 break;
01844 fread(&scratch, 1, 1, f);
01845 }
01846
01847 if(feof(f))
01848 FAILURE(Runtime, "File is too short to be a SRM ROM image");
01849 buffer = PtrToMem(0x900000);
01850 while(!feof(f))
01851 fread(buffer++, 1, 1, f);
01852 fclose(f);
01853
01854 printf("%%SYS-I-DECOMP: Decompressing ROM image.\n0%%");
01855 acCPUs[0]->set_pc(0x900001);
01856 acCPUs[0]->set_PAL_BASE(0x900000);
01857 acCPUs[0]->enable_icache();
01858 acCPUs[1]->set_pc(0x900001);
01859 acCPUs[1]->set_PAL_BASE(0x900000);
01860 acCPUs[1]->enable_icache();
01861
01862 j = 0;
01863 while(acCPUs[0]->get_clean_pc() > 0x200000)
01864 {
01865 for(i = 0; i < 1800000; i++)
01866 {
01867 SingleStep();
01868 if(acCPUs[0]->get_clean_pc() < 0x200000)
01869 break;
01870 }
01871
01872 j++;
01873 if(((j % 5) == 0) && (j < 50))
01874 printf("%d%%", j * 2);
01875 else
01876 printf(".");
01877 fflush(stdout);
01878 }
01879
01880 printf("100%%\n");
01881 acCPUs[0]->restore_icache();
01882 acCPUs[1]->restore_icache();
01883 printf("PC %"LL "x, %"LL "x. \n", acCPUs[0]->get_pc(), acCPUs[1]->get_pc());
01884
01885 f = fopen(myCfg->get_text_value("rom.decompressed", "decompressed.rom"),
01886 "wb");
01887 if(!f)
01888 {
01889 printf("%%SYS-W-NOWRITE: Couldn't write decompressed rom to %s.\n",
01890 myCfg->get_text_value("rom.decompressed", "decompressed.rom"));
01891 }
01892 else
01893 {
01894 printf("%%SYS-I-ROMWRT: Writing decompressed rom to %s.\n",
01895 myCfg->get_text_value("rom.decompressed", "decompressed.rom"));
01896 temp = endian_64(acCPUs[0]->get_pc());
01897 fwrite(&temp, 1, sizeof(u64), f);
01898 temp = endian_64(acCPUs[0]->get_pal_base());
01899 fwrite(&temp, 1, sizeof(u64), f);
01900 buffer = PtrToMem(0);
01901 fwrite(buffer, 1, 0x200000, f);
01902 fclose(f);
01903 }
01904 }
01905 else
01906 {
01907 printf("%%SYS-I-READROM: Reading decompressed ROM image from %s.\n",
01908 myCfg->get_text_value("rom.decompressed", "decompressed.rom"));
01909 fread(&temp, 1, sizeof(u64), f);
01910 for(int i = 0; i < iNumCPUs; i++)
01911 acCPUs[i]->set_pc(endian_64(temp));
01912 fread(&temp, 1, sizeof(u64), f);
01913 for(int i = 0; i < iNumCPUs; i++)
01914 acCPUs[i]->set_PAL_BASE(endian_64(temp));
01915 buffer = PtrToMem(0);
01916 fread(buffer, 1, 0x200000, f);
01917 fclose(f);
01918 }
01919
01920 #if !defined(SRM_NO_SPEEDUPS) || !defined(SRM_NO_IDE)
01921 printf("%%SYM-I-PATCHROM: Patching ROM for speed.\n");
01922 #endif
01923 #if !defined(SRM_NO_SPEEDUPS)
01924 WriteMem(U64(0x14248), 32, 0xe7e00000, 0);
01925 WriteMem(U64(0x14288), 32, 0xe7e00000, 0);
01926 WriteMem(U64(0x142c8), 32, 0xe7e00000, 0);
01927 WriteMem(U64(0x68320), 32, 0xe7e00000, 0);
01928 WriteMem(U64(0x8bb78), 32, 0xe7e00000, 0);
01929 WriteMem(U64(0x8bc0c), 32, 0xe7e00000, 0);
01930 WriteMem(U64(0x8bc94), 32, 0xe7e00000, 0);
01931
01932
01933 #endif
01934 printf("%%SYS-I-ROMLOADED: ROM Image loaded successfully!\n");
01935 return 0;
01936 }
01937
02021 void CSystem::interrupt(int number, bool assert)
02022 {
02023 int i;
02024
02025 if(number == -1)
02026 {
02027
02028
02029 state.cchip.misc |= 0xf0;
02030 for(i = 0; i < iNumCPUs; i++)
02031 acCPUs[i]->irq_h(2, true, 0);
02032 }
02033 else if(assert)
02034 {
02035
02036
02037
02038 state.cchip.drir |= (U64(0x1) << number);
02039 }
02040 else
02041 {
02042
02043
02044
02045 state.cchip.drir &= ~(U64(0x1) << number);
02046 }
02047
02048 for(i = 0; i < iNumCPUs; i++)
02049 {
02050 if(state.cchip.drir & state.cchip.dim[i] & U64(0x00ffffffffffffff))
02051 acCPUs[i]->irq_h(1, true, 100);
02052 else
02053 acCPUs[i]->irq_h(1, false, 0);
02054
02055 if(state.cchip.drir & state.cchip.dim[i] & U64(0xfc00000000000000))
02056 acCPUs[i]->irq_h(0, true, 100);
02057 else
02058 acCPUs[i]->irq_h(0, false, 0);
02059 }
02060 }
02061
02150 u64 CSystem::PCI_Phys(int pcibus, u32 address)
02151 {
02152 u64 a;
02153 int j;
02154
02155 #if defined(DEBUG_PCI)
02156 printf("-------------- PCI MEMORY ACCESS FOR PCI HOSE %d --------------\n",
02157 pcibus);
02158
02159
02160 for(j = 0; j < 4; j++)
02161 {
02162 printf("WSBA%d: %016"LL "x WSM: %016"LL "x TBA: %016"LL "x\n", j,
02163 state.pchip[pcibus].wsba[j], state.pchip[pcibus].wsm[j],
02164 state.pchip[pcibus].tba[j]);
02165 }
02166
02167 printf("HOLE: %s\n",
02168 test_bit_64(state.pchip[pcibus].pctl, 5) ? "enabled" : "disabled");
02169 printf("--------------------------------------------------------------\n");
02170 #endif
02171 if(!(state.pchip[pcibus].pctl & PCI_PCTL_HOLE)
02172 || (address < PCI_PCTL_HOLE_START) || (address > PCI_PCTL_HOLE_END))
02173 {
02174
02175
02176 for(j = 0; j < 4; j++)
02177 {
02178 if((state.pchip[pcibus].wsba[j] & 1)
02179 && !((address ^ state.pchip[pcibus].wsba[j]
02180 ) & 0xfff00000 &~state.pchip[pcibus].wsm[j]))
02181 {
02182 if(state.pchip[pcibus].wsba[j] & 2)
02183 {
02184 try
02185 {
02186 a = PCI_Phys_scatter_gather(address, state.pchip[pcibus].wsm[j],
02187 state.pchip[pcibus].tba[j]);
02188 }
02189
02190 catch (char)
02191 {
02192
02193
02194
02195 return U64(0x80000000000) |
02196 (pcibus * U64(0x200000000)) |
02197 (u64) address;
02198 }
02199 }
02200 else
02201 a = PCI_Phys_direct_mapped(address, state.pchip[pcibus].wsm[j],
02202 state.pchip[pcibus].tba[j]);
02203 #if defined(DEBUG_PCI)
02204 printf("PCI memory address %08x translated to %016"LL "x\n", address, a);
02205 #endif
02206 return a;
02207 }
02208 }
02209 }
02210
02211
02212 return U64(0x80000000000) | (pcibus * U64(0x200000000)) | (u64) address;
02213 }
02214
02248 u64 CSystem::PCI_Phys_direct_mapped(u32 address, u64 wsm, u64 tba)
02249 {
02250 u64 a;
02251
02252 wsm &= PCI_WSM_MASK;
02253
02254 a = (address & (wsm | PCI_ADD_MASK)) | (tba &~wsm & PCI_TBA_MASK);
02255
02256 return a;
02257 }
02258
02327 u64 CSystem::PCI_Phys_scatter_gather(u32 address, u64 wsm, u64 tba)
02328 {
02329 u64 pte_a;
02330
02331 u64 pte;
02332
02333 u64 a;
02334
02335 wsm &= PCI_WSM_MASK;
02336
02337 pte_a = ((address & (wsm | PCI_PTE_ADD_MASK)) >> PCI_PTE_ADD_SHIFT)
02338 | (tba & PCI_PTE_TBA_MASK &~(wsm >> PCI_PTE_ADD_SHIFT));
02339 pte = ReadMem(pte_a, 64, 0);
02340 if(pte & 1)
02341 {
02342 a = ((pte << PCI_PTE_SHIFT) & PCI_PTE_MASK) | (address & PCI_PTE_ADD2_MASK);
02343
02344 if(pte & PCI_PTE_PEER_BIT)
02345 a |= (PHYS_PIO_ACCESS);
02346 return a;
02347 }
02348 else
02349 {
02350 throw((char) '0');
02351 }
02352 }
02353
02357 void CSystem::init()
02358 {
02359 for(int i = 0; i < iNumComponents; i++)
02360 acComponents[i]->init();
02361 }
02362
02363 void CSystem::start_threads()
02364 {
02365 int i;
02366
02367 printf("Start threads:");
02368 for(i = 0; i < iNumComponents; i++)
02369 acComponents[i]->start_threads();
02370 printf("\n");
02371
02372 for(i = 0; i < iNumCPUs; i++)
02373 acCPUs[i]->release_threads();
02374 }
02375
02376 void CSystem::stop_threads()
02377 {
02378 printf("Stop threads:");
02379 for(int i = 0; i < iNumComponents; i++)
02380 acComponents[i]->stop_threads();
02381 printf("\n");
02382 }
02383
02387 void CSystem::SaveState(const char* fn)
02388 {
02389 FILE* f;
02390 int i;
02391 unsigned int m;
02392 unsigned int j;
02393 int* mem = (int*) memory;
02394 int int0 = 0;
02395 unsigned int memints = (1 << iNumMemoryBits) / (unsigned int) sizeof(int);
02396 u32 temp_32;
02397
02398 f = fopen(fn, "wb");
02399 if(f)
02400 {
02401 temp_32 = 0xa1fae540;
02402 fwrite(&temp_32, sizeof(u32), 1, f);
02403 temp_32 = 0x00020001;
02404 fwrite(&temp_32, sizeof(u32), 1, f);
02405
02406
02407 for(m = 0; m < memints; m++)
02408 {
02409 if(mem[m])
02410 {
02411 fwrite(&(mem[m]), 1, sizeof(int), f);
02412 }
02413 else
02414 {
02415 j = 0;
02416 m++;
02417 while(!mem[m] && (m < memints))
02418 {
02419 m++;
02420 j++;
02421 if((int) j == -1)
02422 break;
02423 }
02424
02425 if(mem[m])
02426 m--;
02427 fwrite(&int0, 1, sizeof(int), f);
02428 fwrite(&j, 1, sizeof(int), f);
02429 }
02430 }
02431
02432 fwrite(&state, sizeof(state), 1, f);
02433
02434
02435
02436
02437
02438 for(i = 0; i < iNumComponents; i++)
02439 acComponents[i]->SaveState(f);
02440 fclose(f);
02441 }
02442 }
02443
02447 void CSystem::RestoreState(const char* fn)
02448 {
02449 FILE* f;
02450 int i;
02451 unsigned int m;
02452 unsigned int j;
02453 int* mem = (int*) memory;
02454 unsigned int memints = (1 << iNumMemoryBits) / (unsigned int) sizeof(int);
02455 u32 temp_32;
02456
02457 f = fopen(fn, "rb");
02458 if(!f)
02459 {
02460 printf("%%SYS-F-NOFILE: Can't open restore file %s\n", fn);
02461 return;
02462 }
02463
02464 fread(&temp_32, sizeof(u32), 1, f);
02465 if(temp_32 != 0xa1fae540)
02466 {
02467 printf("%%SYS-F-FORMAT: %s does not appear to be a state file.\n", fn);
02468 return;
02469 }
02470
02471 fread(&temp_32, sizeof(u32), 1, f);
02472
02473 if(temp_32 != 0x00020001)
02474 {
02475 printf("%%SYS-I-VERSION: State file %s is a different version.\n", fn);
02476 return;
02477 }
02478
02479
02480 for(m = 0; m < memints; m++)
02481 {
02482 fread(&(mem[m]), 1, sizeof(int), f);
02483 if(!mem[m])
02484 {
02485 fread(&j, 1, sizeof(int), f);
02486 while(j--)
02487 {
02488 mem[++m] = 0;
02489 }
02490 }
02491 }
02492
02493 fread(&state, sizeof(state), 1, f);
02494
02495
02496
02497
02498
02499 for(i = 0; i < iNumComponents; i++)
02500 {
02501 if(acComponents[i]->RestoreState(f))
02502 FAILURE(Runtime, "Unable to restore system state");
02503 }
02504
02505 fclose(f);
02506 }
02507
02511 void CSystem::DumpMemory(unsigned int filenum)
02512 {
02513 char file[100];
02514 int x;
02515 int* mem = (int*) memory;
02516 FILE* f;
02517
02518 sprintf(file, "memory_%012d.dmp", filenum);
02519 f = fopen(file, "wb");
02520
02521 x = (1 << iNumMemoryBits) / (unsigned int) sizeof(int) / 2;
02522
02523 while(!mem[x - 1])
02524 x--;
02525
02526 fwrite(mem, 1, x * sizeof(int), f);
02527 fclose(f);
02528 }
02529
02533 void CSystem::panic(char* message, int flags)
02534 {
02535 int cpunum;
02536
02537 int i;
02538 CAlphaCPU* cpu;
02539 printf("\n******** SYSTEM PANIC *********\n");
02540 printf("* %s\n", message);
02541 printf("*******************************\n");
02542 for(cpunum = 0; cpunum < iNumCPUs; cpunum++)
02543 {
02544 cpu = acCPUs[cpunum];
02545 printf("\n==================== STATE OF CPU %d ====================\n",
02546 cpunum);
02547
02548 printf("PC: %016"LL "x\n", cpu->get_pc());
02549 #ifdef IDB
02550 printf("Physical PC: %016"LL "x\n", cpu->get_current_pc_physical());
02551 printf("Instruction Count: %"LL "d\n", cpu->get_instruction_count());
02552 #endif
02553 printf("\n");
02554
02555 for(i = 0; i < 32; i++)
02556 {
02557 if(i < 10)
02558 printf("R");
02559 printf("%d:%016"LL "x", i, cpu->get_r(i, false));
02560 if(i % 4 == 3)
02561 printf("\n");
02562 else
02563 printf(" ");
02564 }
02565
02566 printf("\n");
02567 for(i = 4; i < 8; i++)
02568 {
02569 if(i < 10)
02570 printf("S");
02571 printf("%d:%016"LL "x", i, cpu->get_r(i + 32, false));
02572 if(i % 4 == 3)
02573 printf("\n");
02574 else
02575 printf(" ");
02576 }
02577
02578 for(i = 20; i < 24; i++)
02579 {
02580 if(i < 10)
02581 printf("S");
02582 printf("%d:%016"LL "x", i, cpu->get_r(i + 32, false));
02583 if(i % 4 == 3)
02584 printf("\n");
02585 else
02586 printf(" ");
02587 }
02588
02589 printf("\n");
02590 for(i = 0; i < 32; i++)
02591 {
02592 if(i < 10)
02593 printf("F");
02594 printf("%d:%016"LL "x", i, cpu->get_f(i));
02595 if(i % 4 == 3)
02596 printf("\n");
02597 else
02598 printf(" ");
02599 }
02600 }
02601
02602 printf("\n");
02603 #ifdef IDB
02604 if(flags & PANIC_LISTING)
02605 {
02606 u64 start;
02607
02608 u64 end;
02609 start = cpu->get_pc() - 64;
02610 end = start + 128;
02611 cpu->listing(start, end, cpu->get_pc());
02612 }
02613 #endif
02614 if(flags & PANIC_ASKSHUTDOWN)
02615 {
02616 printf("Stop Emulation? ");
02617
02618 int c = getc(stdin);
02619 if(c == 'y' || c == 'Y')
02620 flags |= PANIC_SHUTDOWN;
02621 }
02622
02623 if(flags & PANIC_SHUTDOWN)
02624 {
02625 FAILURE(Abort, "Panic shutdown");
02626 }
02627
02628 return;
02629 }
02630
02634 void CSystem::clear_clock_int(int ProcNum)
02635 {
02636 state.cchip.misc &= ~(U64(0x10) << ProcNum);
02637 acCPUs[ProcNum]->irq_h(2, false, 0);
02638 }
02639
02640 #if defined(PROFILE)
02641 u64 profile_buckets[PROFILE_BUCKETS];
02642 u64 profiled_insts;
02643 bool profile_started = false;
02644 #endif
02645 CSystem* theSystem = 0;