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

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"
1.1.1.19  root       18: #include "event.h"
1.1.1.6   root       19: #include "interrupt.h"
1.1.1.16  root       20: #include "monitor.h"
1.1.1.10  root       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);
1.1.1.20! root       29:        monitor->SetCallback(&SysClkDevice::MonitorScreen);
1.1.1.19  root       30:        monitor->SetSize(32, 4);
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:        interrupt = GetInterruptDevice();
                     43: 
1.1.1.4   root       44:        // クロックは機種ごとに異なる
1.1.1.14  root       45:        const ConfigItem& item = gConfig->Find("!sysclk-freq");
                     46:        freq = item.AsInt();
                     47:        period = 1_sec / freq;
1.1.1.9   root       48: 
                     49:        // クロックの同期方法
1.1.1.19  root       50:        syncer = GetSyncer();
1.1.1.18  root       51:        sync_rt = syncer->GetSyncRealtime();
1.1.1.9   root       52: 
1.1.1.19  root       53:        auto evman = GetEventManager();
                     54:        event = evman->Regist(this,
                     55:                ToEventCallback(&SysClkDevice::Callback),
                     56:                "System Clock");
                     57:        event->time = period;
1.1.1.15  root       58: 
1.1.1.4   root       59:        return true;
                     60: }
                     61: 
1.1.1.10  root       62: // 電源オン/リセット
                     63: void
                     64: SysClkDevice::ResetHard(bool poweron)
1.1       root       65: {
1.1.1.10  root       66:        // XXX たぶん電源オンだけで作用する?
                     67:        if (poweron) {
                     68:                if (sync_rt) {
1.1.1.12  root       69:                        stime = GetSyncer()->GetRealTime();
1.1.1.10  root       70:                }
                     71: 
                     72:                // 電源オンですぐ起動
1.1.1.12  root       73:                scheduler->RestartEvent(event);
1.1.1.9   root       74:        }
1.1.1.14  root       75: 
                     76:        // さすがに割り込みネゲートくらいするよな?
                     77:        sysint = false;
                     78:        ChangeInterrupt();
1.1       root       79: }
                     80: 
1.1.1.14  root       81: busdata
1.1.1.15  root       82: SysClkDevice::ReadPort(uint32 offset)
1.1       root       83: {
1.1.1.3   root       84:        // 1 ポートしかない
1.1.1.15  root       85:        busdata data = GetInt();
                     86:        data |= BusData::Size1;
                     87:        return data;
1.1.1.3   root       88: }
1.1       root       89: 
1.1.1.14  root       90: busdata
1.1.1.15  root       91: SysClkDevice::WritePort(uint32 offset, uint32 data)
1.1.1.3   root       92: {
                     93:        // 何か書き込まれたら、フラグをクリア
1.1.1.11  root       94:        putlog(3, "Clear system clock interrupt");
1.1.1.6   root       95:        sysint = false;
1.1.1.14  root       96:        ChangeInterrupt();
1.1.1.15  root       97: 
                     98:        busdata r = BusData::Size1;
                     99:        return r;
1.1       root      100: }
                    101: 
1.1.1.14  root      102: busdata
1.1.1.15  root      103: SysClkDevice::PeekPort(uint32 offset)
1.1       root      104: {
1.1.1.3   root      105:        return GetInt();
                    106: }
                    107: 
1.1.1.15  root      108: bool
                    109: SysClkDevice::PokePort(uint32 offset, uint32 data)
                    110: {
                    111:        return false;
                    112: }
                    113: 
1.1.1.9   root      114: void
1.1.1.20! root      115: SysClkDevice::MonitorScreen(Monitor *, TextScreen& screen)
1.1.1.9   root      116: {
                    117:        int y;
                    118: 
                    119:        screen.Clear();
                    120:        y = 0;
                    121: 
                    122:        int width = stime < 86400_sec ? 20 : 25;
1.1.1.15  root      123:        screen.Print(0, y++, "Freq: %u Hz", freq);
1.1.1.19  root      124:        if (sync_rt) {
                    125:                screen.Puts(0,  y++, "Sync: Real Time");
                    126:                screen.Print(0, y++, "Time:  %*s", width, TimeToStr(stime).c_str());
                    127: 
                    128:                // TimeToStr は負は想定していないし、符号は数値の直前に足したい。
                    129:                screen.Puts(0, y, "Diff:");
                    130:                bool neg = false;
                    131:                if (delta < 0) {
                    132:                        delta = -delta;
                    133:                        neg = true;
                    134:                }
                    135:                std::string s = TimeToStr(delta);
                    136:                int offset = width - s.size();
                    137:                screen.Print(6 + offset, y++, "%c%s", (neg ? '-' : '+'), s.c_str());
                    138:        } else {
                    139:                screen.Puts(0, y++, "Sync: Virtual Time");
                    140:                screen.Puts(0, y++, TA::Disable, "Time:");
                    141:                screen.Puts(0, y++, TA::Disable, "Diff:");
                    142:        }
1.1.1.9   root      143: }
                    144: 
1.1.1.3   root      145: // 割り込み状態を取得(?)
                    146: uint8
                    147: SysClkDevice::GetInt() const
                    148: {
                    149:        uint8 data = 0;
1.1       root      150: 
1.1.1.3   root      151:        if (sysint) {
                    152:                data |= 0x80;
1.1       root      153:        }
1.1.1.3   root      154:        return data;
1.1       root      155: }
                    156: 
                    157: // イベントハンドラ
                    158: void
1.1.1.19  root      159: SysClkDevice::Callback(Event *ev)
1.1       root      160: {
1.1.1.11  root      161:        putlog(3, "Interrupt occured");
1.1.1.9   root      162: 
1.1.1.10  root      163:        sysint = true;
1.1.1.14  root      164:        ChangeInterrupt();
1.1.1.9   root      165: 
1.1.1.10  root      166:        if (sync_rt) {
1.1.1.18  root      167:                // システムクロックとしての現在時刻。
                    168:                // 足す前は前回の割り込み発生時刻なので period を足すと現在時刻。
                    169:                stime += period;
                    170: 
1.1.1.19  root      171:                // ホスト時間とここで作った実時間との差。
                    172:                uint64 now = syncer->GetRealTime();
                    173:                delta = (int64)(now - stime);
                    174: 
1.1.1.12  root      175:                scheduler->StartRealtimeEvent(ev, stime, period);
1.1.1.9   root      176:        } else {
1.1.1.12  root      177:                scheduler->StartEvent(ev);
1.1.1.9   root      178:        }
1.1       root      179: }
1.1.1.14  root      180: 
                    181: // 割り込み信号線の状態を変える。
                    182: void
                    183: SysClkDevice::ChangeInterrupt()
                    184: {
                    185:        interrupt->ChangeINT(this, sysint);
                    186: }

unix.superglobalmegacorp.com

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