|
|
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.8 root 7: //
8: // VM (基本クラス)
9: //
10:
1.1 root 11: #include "vm.h"
1.1.1.9 ! root 12: #include "debugger.h"
1.1.1.3 root 13: #include "mainapp.h"
1.1.1.9 ! root 14: #include "mainbus.h"
! 15: #include "mainram.h"
1.1 root 16: #include "mpu.h"
1.1.1.8 root 17: #include "power.h"
1.1 root 18: #include "scheduler.h"
1.1.1.8 root 19: #include "signalthread.h"
1.1.1.9 ! root 20: #include "syncer.h"
1.1 root 21:
1.1.1.8 root 22: // グローバル参照用
23: VM *gVM;
1.1 root 24:
25: // コンストラクタ
1.1.1.3 root 26: VM::VM()
1.1 root 27: {
1.1.1.8 root 28: // SignalThread は他のスレッドより先に起動する必要があるので、先頭。
29: // Scheduler は以降の他のデバイスからのイベント登録を受け付ける必要が
30: // あるためその次。
31: NEWDV(SignalThread, new SignalThread());
32: NEWDV(Scheduler, new Scheduler());
1.1.1.9 ! root 33: NEWDV(Syncer, new Syncer());
1.1.1.8 root 34: NEWDV(Power, new PowerDevice());
35: NEWDV(Debugger, new Debugger());
1.1 root 36:
1.1.1.9 ! root 37: NEWDV(Mainbus, new MainbusDevice());
1.1.1.8 root 38: NEWDV(BusErr, new BusErrDevice());
1.1 root 39: }
40:
41: // デストラクタ
42: VM::~VM()
43: {
1.1.1.4 root 44: Dispose();
1.1.1.8 root 45: gVM = NULL;
1.1.1.4 root 46: }
47:
48: // 終了
49: void
50: VM::Dispose()
51: {
1.1.1.8 root 52: // まずスレッドを止める。
53: // デバッガスレッドがスケジューラスレッドにアクセスするのでデバッガが先。
54: if ((bool)pDebugger) {
1.1.1.9 ! root 55: GetDebugger()->TerminateThread();
1.1.1.8 root 56: }
57: if ((bool)pScheduler) {
1.1.1.9 ! root 58: GetScheduler()->TerminateThread();
1.1.1.8 root 59: }
60:
61: // 残りのスレッドを停止
62: for (auto obj : gMainApp.GetObjects()) {
63: auto th = dynamic_cast<ThreadDevice *>(obj);
64: if (th) {
65: th->TerminateThread();
66: }
1.1.1.4 root 67: }
1.1.1.8 root 68:
69: // 作ったときと逆順で解放する
70: if ((bool)pDebugger) {
71: pDebugger.reset();
72: }
73:
74: if ((bool)pScheduler) {
75: pScheduler.reset();
76: }
77:
78: // ほかのオブジェクトの解放はグローバルデストラクタにおまかせ。
79: // だめだったらまた考える。
1.1 root 80: }
81:
82: // コンストラクタ後の初期化
83: bool
84: VM::Create()
85: {
1.1.1.8 root 86: // d->Create() は Object を追加する場合があるため、ここで
1.1.1.7 root 87: // ranged for は使えない。また追加されたデバイスの Create() も(念のため)
88: // 実行したいため、ループ終了条件で毎回 size() を取り出して比較する。
1.1.1.8 root 89: for (int i = 0; i < gMainApp.GetObjects().size(); i++) {
90: auto dev = dynamic_cast<Device *>(gMainApp.GetObjects()[i]);
91: if (dev) {
92: if (!dev->Create()) {
93: return false;
94: }
1.1 root 95: }
96: }
97:
98: return true;
99: }
100:
101: // 初期化
102: bool
103: VM::Init()
104: {
1.1.1.8 root 105: for (auto obj : gMainApp.GetObjects()) {
106: auto dev = dynamic_cast<Device *>(obj);
107: if (dev) {
108: if (!dev->Init()) {
109: return false;
110: }
111: }
112: }
113:
114: return true;
115: }
116:
117: // スレッド開始
118: bool
119: VM::StartThread()
120: {
121: for (auto obj : gMainApp.GetObjects()) {
122: auto th = dynamic_cast<ThreadDevice *>(obj);
123: if (th) {
124: if (!th->StartThread()) {
125: return false;
126: }
1.1 root 127: }
128: }
129:
130: return true;
131: }
132:
133: // 設定の適用
134: bool
135: VM::Apply()
136: {
1.1.1.8 root 137: for (auto obj : gMainApp.GetObjects()) {
138: auto dev = dynamic_cast<Device *>(obj);
139: if (dev) {
140: if (!dev->Apply()) {
141: return false;
142: }
1.1 root 143: }
144: }
145:
146: return true;
147: }
148:
1.1.1.7 root 149: // ブートページを切り替える (共通処理)
150: // 派生クラスから呼ぶこと。
1.1 root 151: void
1.1.1.7 root 152: VM::SwitchBootPage(Device *parent, bool isrom)
1.1 root 153: {
1.1.1.7 root 154: // ログ表示
155: if (isrom) {
156: parent->putlogf(1, lstr("SwitchBootPage ROM (Boot)"));
157: } else {
158: parent->putlogf(1, lstr("SwitchBootPage RAM (Normal)"));
1.1 root 159: }
1.1.1.7 root 160:
1.1.1.8 root 161: // 同期モード指示
1.1.1.9 ! root 162: GetSyncer()->RequestBootPageMode(isrom);
1.1.1.8 root 163: }
164:
165: // MPU の RESET 命令によるリセット
166: void
167: VM::ResetByMPU()
168: {
1.1 root 169: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.