User Tag List

Показано с 1 по 4 из 4

Тема: Эмуляция встроенного таймера процессора 1801ВМ1

Комбинированный просмотр

Предыдущее сообщение Предыдущее сообщение   Следующее сообщение Следующее сообщение
  1. #1

    Регистрация
    11.09.2009
    Адрес
    Москва
    Сообщений
    4,805
    Спасибо Благодарностей отдано 
    9
    Спасибо Благодарностей получено 
    147
    Поблагодарили
    78 сообщений
    Mentioned
    16 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию

    Дополнительные тесты позволили выявить несколько ошибок и неточностей в первой версии алгоритма.

    Вот новая версия алгоритма, ещё более точно (как я полагаю) эмулирующая работу встроенного таймера процессора 1801ВМ1:

    Код:
    typedef unsigned long long QWORD;
    typedef unsigned long      DWORD;
    typedef unsigned short     word;
    
    #define WORD(a) (*(unsigned short *)&aMemory[a])
    
    PowerON()
    {
      WORD(0177706) = wCPU_ID;
      wVE_Timer_Counter = 0177777;
      WORD(0177710) = wVE_Timer_Counter;
      WORD(0177712) = 0177400;
      nVE_MonitoredExpiryCount = 0;
      bVE_Expiry = false;
      bVE_Go = false;
    }
    
    Reset()
    {
      WORD(0177712) = 0;
      Last_IO_Mode = IO_WRITE;
      wLast_IO_Addr =  0177712;
      Make_IO();
    }
    
    Make_IO()
    {
      switch( wLast_IO_Addr )
      {
        // VE-Timer Counter Initial Value
        case 0177706:
        {
          if( Last_IO_Mode == IO_WRITE )
          {
            Last_IO_Mode = IO_READ;
            wLast_IO_Addr =  0177710;
            Make_IO();
            Last_IO_Mode = IO_WRITE;
            wLast_IO_Addr =  0177706;
    
            if( bVE_Go && !bVE_NoReload && !bVE_NoRestart )
            {
              QWORD qwCurrentCPU_RunTimeNS = qwCPU_TotalRunTimeNS;
              qwCurrentCPU_RunTimeNS += dwCurrentStepsLatencyNS;
              QWORD qwCurrentCPU_Clocks = qwCurrentCPU_RunTimeNS/uCPU_CycleNS;
              
              if( qwCurrentCPU_Clocks >= qwNextVE_TimerStart_CPU_Clocks )
              {
                qwPrevVE_TimerStart_CPU_Clocks = qwNextVE_TimerStart_CPU_Clocks;
                dwPrevInitialVE_CounterVal     = dwNextInitialVE_CounterVal;
                
                QWORD qwUsedCPU_Clocks = qwCurrentCPU_Clocks - qwPrevVE_TimerStart_CPU_Clocks;
                QWORD qwCurrentVE_Timer_Clocks = qwUsedCPU_Clocks/nVE_CPU_Clock_Divider;
              
                DWORD dwTimerClocksLow = qwCurrentVE_Timer_Clocks % dwPrevInitialVE_CounterVal;
                
                qwNextVE_TimerStart_CPU_Clocks = qwPrevVE_TimerStart_CPU_Clocks;
                qwNextVE_TimerStart_CPU_Clocks += ( dwPrevInitialVE_CounterVal - dwTimerClocksLow ) * nVE_CPU_Clock_Divider;
              }
              
              dwNextInitialVE_CounterVal = WORD(0177706);
              if( !dwNextInitialVE_CounterVal ) { dwNextInitialVE_CounterVal = 0x10000; }
            }
          }
        }
        break;
        
        // VE-Timer Counter
        case 0177710:
        {
          if( Last_IO_Mode == IO_WRITE )
          {
            WORD(0177710) = wVE_Timer_Counter;
          }
          else
          {
            if( bVE_Go )
            {
              QWORD qwCurrentCPU_RunTimeNS = qwCPU_TotalRunTimeNS;
              qwCurrentCPU_RunTimeNS += dwCurrentStepsLatencyNS;
              QWORD qwCurrentCPU_Clocks = qwCurrentCPU_RunTimeNS/uCPU_CycleNS;
              
              QWORD qwVE_TimerStart_CPU_Clocks = qwPrevVE_TimerStart_CPU_Clocks;
              DWORD dwInitialVE_CounterVal     = dwPrevInitialVE_CounterVal;
              
              if( qwCurrentCPU_Clocks >= qwNextVE_TimerStart_CPU_Clocks )
              {
                bVE_Expiry = true;
                
                if( !bVE_NoRestart )
                {
                  qwVE_TimerStart_CPU_Clocks = qwNextVE_TimerStart_CPU_Clocks;
                  dwInitialVE_CounterVal     = dwNextInitialVE_CounterVal;
                }
              }
              
              QWORD qwUsedCPU_Clocks = qwCurrentCPU_Clocks - qwVE_TimerStart_CPU_Clocks;
              QWORD qwCurrentVE_Timer_Clocks = qwUsedCPU_Clocks/nVE_CPU_Clock_Divider;
              
              DWORD dwTimerClocksHi  = qwCurrentVE_Timer_Clocks / dwInitialVE_CounterVal;
              DWORD dwTimerClocksLow = qwCurrentVE_Timer_Clocks % dwInitialVE_CounterVal;
    
              if( bVE_Expiry )
              {
                if( bVE_Monitor && (dwTimerClocksHi > nVE_MonitoredExpiryCount) )
                {
                  nVE_MonitoredExpiryCount = dwTimerClocksHi;
                }
                
                if( bVE_NoReload )
                {
                  wVE_Timer_Counter = dwInitialVE_CounterVal - dwTimerClocksLow;
                }
                else if( bVE_NoRestart )
                {
                  bVE_Go = false;
                  
                  wVE_Timer_Counter = WORD(0177706);
    
                  if( dwTimerClocksHi == 1 && !dwTimerClocksLow )
                  {
                    if( qwCurrentCPU_Clocks%128 < 5 )
                    {
                      wVE_Timer_Counter = 0;
                    }
                  }            
                }
                else
                {
                  wVE_Timer_Counter = dwInitialVE_CounterVal - dwTimerClocksLow;
                  
                  if( !dwTimerClocksLow )
                  {
                    if( qwCurrentCPU_Clocks%128 < 5 )
                    {
                      wVE_Timer_Counter = 0;
                    }
                  }
                }
              }
              else
              { // !bVE_Expiry
                wVE_Timer_Counter = dwInitialVE_CounterVal - dwTimerClocksLow;
              }
              
              WORD(0177710) = wVE_Timer_Counter;
            }
          }
        }
        break;
        
        // VE-Timer CSR
        case 0177712:
        {
          IO_ModeType IO_Mode = Last_IO_Mode;
          
          Last_IO_Mode = IO_READ;
          wLast_IO_Addr =  0177710;
          Make_IO();
          wLast_IO_Addr =  0177712;
          Last_IO_Mode = IO_Mode;
    
          word wVE_Timer_CSR = WORD(0177712);
    
          if( Last_IO_Mode == IO_READ )
          {
            if( bVE_Expiry )
            {
              if( bVE_Monitor && nVE_MonitoredExpiryCount > 1 )
              {
                wVE_Timer_CSR |= BIT_7;
              }
              
              if( bVE_NoRestart && !bVE_NoReload )
              {
                wVE_Timer_CSR &= ~BIT_4;
              }
            }
            WORD(0177712) = wVE_Timer_CSR|0xFF00;
          }
          else
          { // Last_IO_Mode == IO_WRITE
          
            if( nVE_MonitoredExpiryCount )
            {
              nVE_MonitoredExpiryCount = 2;
            }
          
            bVE_Expiry = false;
            
            bVE_Go = wVE_Timer_CSR & BIT_4;
    
            if( wVE_Timer_CSR & BIT_0 )
            {
              bVE_Go = false;
            }
    
            bVE_NoReload  = wVE_Timer_CSR & BIT_1;
            bVE_Monitor   = wVE_Timer_CSR & BIT_2;
            bVE_NoRestart = wVE_Timer_CSR & BIT_3;
    
            nVE_CPU_Clock_Divider = 128;
            
            if( wVE_Timer_CSR & BIT_5 )
            {
              nVE_CPU_Clock_Divider *= 16;
            }
    
            if( wVE_Timer_CSR & BIT_6 )
            {
              nVE_CPU_Clock_Divider *= 4;
            }
    
            
            if( bVE_Go )
            {
              QWORD qwCurrentCPU_RunTimeNS = qwCPU_TotalRunTimeNS;
              qwCurrentCPU_RunTimeNS += dwCurrentStepsLatencyNS;
              QWORD qwCurrentCPU_Clocks = qwCurrentCPU_RunTimeNS/uCPU_CycleNS;
              
              QWORD qwVE_TimerStart_CPU_Clocks = qwCurrentCPU_Clocks;
              qwVE_TimerStart_CPU_Clocks -= qwVE_TimerStart_CPU_Clocks%128;
    
              QWORD dwInitialVE_CounterVal = WORD(0177706);
              if( !dwInitialVE_CounterVal ) { dwInitialVE_CounterVal = 0x10000; }
              
              dwPrevInitialVE_CounterVal = dwInitialVE_CounterVal;
              dwNextInitialVE_CounterVal = dwInitialVE_CounterVal;
              
              if( bVE_NoReload )
              {
                dwNextInitialVE_CounterVal = 0x10000;
              }
    
              qwPrevVE_TimerStart_CPU_Clocks = qwVE_TimerStart_CPU_Clocks;
              qwNextVE_TimerStart_CPU_Clocks = qwVE_TimerStart_CPU_Clocks;
              qwNextVE_TimerStart_CPU_Clocks += dwInitialVE_CounterVal * nVE_CPU_Clock_Divider;
            }
    
            wVE_Timer_Counter = WORD(0177706);
            
            WORD(0177710) = wVE_Timer_Counter;
            WORD(0177712) = wVE_Timer_CSR|0xFF00;
          }
        }
        break;
      }
    }

  2. #1
    С любовью к вам, Yandex.Direct
    Размещение рекламы на форуме способствует его дальнейшему развитию

Информация о теме

Пользователи, просматривающие эту тему

Эту тему просматривают: 1 (пользователей: 0 , гостей: 1)

Похожие темы

  1. Форт для процессора 6502
    от rw6hrm в разделе Зарубежные компьютеры
    Ответов: 7
    Последнее: 15.10.2010, 15:01
  2. VHDL-модель процессора Motorola 68000
    от ILoveSpeccy в разделе Несортированное железо
    Ответов: 60
    Последнее: 30.01.2008, 17:09
  3. О шине данных процессора...
    от ILoveSpeccy в разделе Несортированное железо
    Ответов: 25
    Последнее: 01.08.2007, 16:42
  4. Нужна помощь с выбором процессора Z80...
    от ILoveSpeccy в разделе Несортированное железо
    Ответов: 6
    Последнее: 04.05.2007, 02:38

Ваши права

  • Вы не можете создавать новые темы
  • Вы не можете отвечать в темах
  • Вы не можете прикреплять вложения
  • Вы не можете редактировать свои сообщения
  •