|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.