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

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

unix.superglobalmegacorp.com

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