Annotation of nono/vm/sysclk.cpp, revision 1.1.1.18

1.1       root        1: //
                      2: // nono
1.1.1.4   root        3: // Copyright (C) 2020 nono project
                      4: // Licensed under nono-license.txt
1.1       root        5: //
                      6: 
1.1.1.10  root        7: //
                      8: // LUNA システムクロック
                      9: //
                     10: 
1.1.1.9   root       11: // システムクロックは実時間または仮想時間のいずれかに同期するため、
                     12: // システムクロック独自の時刻 stime を持つ。
                     13: // stime は、割り込みを発生させるごとに、LUNA-I なら 16.67msec、
1.1.1.12  root       14: // LUNA-88K なら 10msec 進行する。
1.1.1.9   root       15: 
1.1       root       16: #include "sysclk.h"
1.1.1.6   root       17: #include "config.h"
                     18: #include "interrupt.h"
1.1.1.16  root       19: #include "monitor.h"
1.1.1.10  root       20: #include "scheduler.h"
1.1.1.12  root       21: #include "syncer.h"
1.1       root       22: 
1.1.1.10  root       23: // コンストラクタ
1.1       root       24: SysClkDevice::SysClkDevice()
1.1.1.12  root       25:        : inherited(OBJ_SYSCLK)
1.1       root       26: {
1.1.1.16  root       27:        monitor = gMonitorManager->Regist(ID_MONITOR_SYSCLK, this);
                     28:        monitor->func = ToMonitorCallback(&SysClkDevice::MonitorUpdate);
                     29:        monitor->SetSize(31, 3);
1.1       root       30: }
                     31: 
1.1.1.10  root       32: // デストラクタ
1.1       root       33: SysClkDevice::~SysClkDevice()
                     34: {
                     35: }
                     36: 
1.1.1.12  root       37: // 初期化
1.1       root       38: bool
1.1.1.4   root       39: SysClkDevice::Init()
                     40: {
1.1.1.12  root       41:        interrupt = GetInterruptDevice();
                     42: 
1.1.1.4   root       43:        // クロックは機種ごとに異なる
1.1.1.14  root       44:        const ConfigItem& item = gConfig->Find("!sysclk-freq");
                     45:        freq = item.AsInt();
                     46:        period = 1_sec / freq;
1.1.1.9   root       47:        event.time = period;
                     48: 
                     49:        // クロックの同期方法
1.1.1.18! root       50:        auto syncer = GetSyncer();
        !            51:        sync_rt = syncer->GetSyncRealtime();
1.1.1.9   root       52: 
1.1.1.15  root       53:        event.func = ToEventCallback(&SysClkDevice::Callback);
                     54:        event.code = 0;
                     55:        event.SetName("System Clock");
                     56:        scheduler->RegistEvent(event);
                     57: 
1.1.1.4   root       58:        return true;
                     59: }
                     60: 
1.1.1.10  root       61: // 電源オン/リセット
                     62: void
                     63: SysClkDevice::ResetHard(bool poweron)
1.1       root       64: {
1.1.1.10  root       65:        // XXX たぶん電源オンだけで作用する?
                     66:        if (poweron) {
                     67:                if (sync_rt) {
1.1.1.12  root       68:                        stime = GetSyncer()->GetRealTime();
1.1.1.10  root       69:                }
                     70: 
                     71:                // 電源オンですぐ起動
1.1.1.12  root       72:                scheduler->RestartEvent(event);
1.1.1.9   root       73:        }
1.1.1.14  root       74: 
                     75:        // さすがに割り込みネゲートくらいするよな?
                     76:        sysint = false;
                     77:        ChangeInterrupt();
1.1       root       78: }
                     79: 
1.1.1.14  root       80: busdata
1.1.1.15  root       81: SysClkDevice::ReadPort(uint32 offset)
1.1       root       82: {
1.1.1.3   root       83:        // 1 ポートしかない
1.1.1.15  root       84:        busdata data = GetInt();
                     85:        data |= BusData::Size1;
                     86:        return data;
1.1.1.3   root       87: }
1.1       root       88: 
1.1.1.14  root       89: busdata
1.1.1.15  root       90: SysClkDevice::WritePort(uint32 offset, uint32 data)
1.1.1.3   root       91: {
                     92:        // 何か書き込まれたら、フラグをクリア
1.1.1.11  root       93:        putlog(3, "Clear system clock interrupt");
1.1.1.6   root       94:        sysint = false;
1.1.1.14  root       95:        ChangeInterrupt();
1.1.1.15  root       96: 
                     97:        busdata r = BusData::Size1;
                     98:        return r;
1.1       root       99: }
                    100: 
1.1.1.14  root      101: busdata
1.1.1.15  root      102: SysClkDevice::PeekPort(uint32 offset)
1.1       root      103: {
1.1.1.3   root      104:        return GetInt();
                    105: }
                    106: 
1.1.1.15  root      107: bool
                    108: SysClkDevice::PokePort(uint32 offset, uint32 data)
                    109: {
                    110:        return false;
                    111: }
                    112: 
1.1.1.9   root      113: void
                    114: SysClkDevice::MonitorUpdate(Monitor *, TextScreen& screen)
                    115: {
                    116:        int y;
                    117: 
                    118:        screen.Clear();
                    119:        y = 0;
                    120: 
                    121:        int width = stime < 86400_sec ? 20 : 25;
1.1.1.15  root      122:        screen.Print(0, y++, "Freq: %u Hz", freq);
1.1.1.9   root      123:        screen.Print(0, y++, "Sync: %s", sync_rt ? "Real Time" : "Virtual Time");
                    124:        screen.Print(0, y++, "Time: %*s", width, TimeToStr(stime).c_str());
                    125: }
                    126: 
1.1.1.3   root      127: // 割り込み状態を取得(?)
                    128: uint8
                    129: SysClkDevice::GetInt() const
                    130: {
                    131:        uint8 data = 0;
1.1       root      132: 
1.1.1.3   root      133:        if (sysint) {
                    134:                data |= 0x80;
1.1       root      135:        }
1.1.1.3   root      136:        return data;
1.1       root      137: }
                    138: 
                    139: // イベントハンドラ
                    140: void
1.1.1.5   root      141: SysClkDevice::Callback(Event& ev)
1.1       root      142: {
1.1.1.11  root      143:        putlog(3, "Interrupt occured");
1.1.1.9   root      144: 
1.1.1.10  root      145:        sysint = true;
1.1.1.14  root      146:        ChangeInterrupt();
1.1.1.9   root      147: 
1.1.1.10  root      148:        if (sync_rt) {
1.1.1.18! root      149:                // システムクロックとしての現在時刻。
        !           150:                // 足す前は前回の割り込み発生時刻なので period を足すと現在時刻。
        !           151:                stime += period;
        !           152: 
1.1.1.12  root      153:                scheduler->StartRealtimeEvent(ev, stime, period);
1.1.1.9   root      154:        } else {
1.1.1.12  root      155:                scheduler->StartEvent(ev);
1.1.1.9   root      156:        }
1.1       root      157: }
1.1.1.14  root      158: 
                    159: // 割り込み信号線の状態を変える。
                    160: void
                    161: SysClkDevice::ChangeInterrupt()
                    162: {
                    163:        interrupt->ChangeINT(this, sysint);
                    164: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.