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