|
|
1.1 root 1: //
2: // nono
3: // Copyright (C) 2020 nono project
4: // Licensed under nono-license.txt
5: //
6:
7: //
1.1.1.3 root 8: // メインバス (共通部分)
1.1 root 9: //
10:
11: #pragma once
12:
13: #include "device.h"
1.1.1.3 root 14: #include "bus.h"
1.1.1.5 ! root 15: #include "textscreen.h"
1.1 root 16: #include <array>
1.1.1.2 root 17: #include <utility>
1.1 root 18:
1.1.1.3 root 19: // メインバスの素質を持つクラス
20: class MainbusBaseDevice : public IODevice
1.1 root 21: {
1.1.1.3 root 22: using inherited = IODevice;
1.1 root 23: public:
1.1.1.4 root 24: explicit MainbusBaseDevice(uint objid_);
1.1.1.3 root 25: ~MainbusBaseDevice() override;
1.1 root 26:
1.1.1.3 root 27: // メインバスの初期化
28: virtual bool InitMainbus() = 0;
1.1 root 29:
1.1.1.3 root 30: // MPU からのリセット (ここ?)
31: virtual void ResetByMPU();
1.1 root 32:
1.1.1.3 root 33: // ブートページを ROM に切り替える
34: void SwitchBootPageToROM() { SwitchBootPage(true); }
35: // ブートページを RAM に切り替える
36: void SwitchBootPageToRAM() { SwitchBootPage(false); }
1.1 root 37:
1.1.1.3 root 38: // モニタ表示用にデバイス名を整形。
1.1.1.2 root 39: static std::pair<std::string, TA> FormatDevName(const Device *dev);
40:
1.1.1.3 root 41: protected:
42: // ブートページを切り替える (内部用)
43: virtual void SwitchBootPage(bool isrom) = 0;
44: };
45:
1.1.1.4 root 46: // 定数クラス。本当はインタフェースっぽくしたい
47: class AccStat
48: {
49: public:
50: // アクセス状況を記録・表示する際に切り捨てる下位ビット数
51: static const uint SHIFT = 21;
52:
53: // メイン空間とバンクメモリ(1枚分)の要素数
54: static const uint MAINLEN = (1 << (32 - SHIFT));
55: static const uint BANKLEN = (1 << (24 - SHIFT));
56:
57: // アクセス状況
58: static const uint8 WRITE = 0x01;
59: static const uint8 READ = 0x02;
60: };
61:
1.1.1.3 root 62: // メインバス (システムに1つ)
63: class MainbusDevice : public MainbusBaseDevice
64: {
65: using inherited = MainbusBaseDevice;
1.1.1.4 root 66: friend class WXAccStatPanel;
67:
1.1.1.3 root 68: public:
1.1.1.4 root 69: // ダイナミックバスサイジング処理用のマクロっぽい関数。
70: // 使い方は HVReadN()、HVWriteN() を参照。
71:
72: // 読み込み後の処理。
73: // addr は読み込みに使ったアドレス、bd は読み込んだデータ。
74: // 次の読み込み用にアドレスとサイズを更新して addr に書き戻す。
75: static inline uint32
76: DYNAMIC_BUS_SIZING_R(busaddr& addr, busdata bd)
77: {
78: uint32 reqsize = addr.GetSize();
79: uint32 portsize = bd.GetSize();
80: uint32 offset = addr.Addr() & (portsize - 1);
81: uint32 datasize = portsize - offset;
82: uint32 tmp = bd.Data();
83: uint32 mask = 0xffffffffU >> ((4 - datasize) * 8);
84: tmp &= mask;
85: if (datasize == reqsize) {
86: addr += reqsize;
87: addr.ChangeSize(0);
88: } else if (datasize > reqsize) {
89: tmp >>= (datasize - reqsize) * 8;
90: addr += reqsize;
91: addr.ChangeSize(0);
92: } else {
93: tmp <<= (reqsize - datasize) * 8;
94: addr += datasize;
95: addr.ChangeSize(reqsize - datasize);
96: }
97:
98: // 今回読み出した値を所定の位置に左シフトしたものを返す。
99: return tmp;
100: }
101:
102: // 書き込み後の処理部分。
103: // addr、data は書き込みに使ったアドレスとデータ。r が書き込みの応答。
104: // 次の書き込み用に、addr はアドレスとサイズを更新したもの、
105: // data も使い終わった上位バイトをクリアしたものを書き戻す。
106: static inline void
107: DYNAMIC_BUS_SIZING_W(busaddr& addr, uint32& data, busdata r)
108: {
109: uint32 reqsize = addr.GetSize();
110: uint32 portsize = r.GetSize();
111: uint32 offset = addr.Addr() & (portsize - 1);
112: uint32 datasize = std::min(portsize - offset, reqsize);
113:
114: addr += datasize;
115: reqsize -= datasize;
116: addr.ChangeSize(reqsize);
117: data &= (1U << (reqsize * 8)) - 1;
118: }
1.1 root 119:
1.1.1.3 root 120: public:
1.1.1.4 root 121: explicit MainbusDevice(uint objid_);
1.1.1.3 root 122: ~MainbusDevice() override;
1.1 root 123:
1.1.1.4 root 124: bool Init() override;
125: void ResetHard(bool poweron) override;
126:
1.1.1.3 root 127: // ハイパーバイザ的アクセスというか、
128: // 今となってはミスアライン可能なアクセスというだけかも知れない。
1.1.1.4 root 129: busdata HVRead1(uint32 addr);
130: busdata HVRead2(uint32 addr);
131: busdata HVRead4(uint32 addr);
132: busdata HVWrite1(uint32 addr, uint32 data);
133: busdata HVWrite2(uint32 addr, uint32 data);
134: busdata HVWrite4(uint32 addr, uint32 data);
135: // サイズを addr で指定する版
136: busdata HVReadN(busaddr addr);
137: busdata HVWriteN(busaddr addr, uint32 data);
1.1.1.2 root 138:
1.1.1.4 root 139: uint64 Peek4(uint32 addr);
140:
141: protected:
142: DECLARE_MONITOR_CALLBACK(MonitorUpdateAccStat);
143:
144: // アクセス状況は 32bit 空間全域を 2048 * 2MB ずつ。
145: // (NEWS は読み出し時にマージする)
146: std::array<uint8, AccStat::MAINLEN> accstat_read {};
147: std::array<uint8, AccStat::MAINLEN> accstat_write {};
148: // R, W をマージした表示用(要素数は機種による)
149: std::vector<uint8> accstat_rw {};
150: // デバイスの存在有無。MSB 側から 1bit = 16MB のビットマップ。
151: std::array<uint8, 32> accstat_avail {};
152: // アクセス状況のアドレス表示オフセット。NEWS だけ 0xc0
153: uint accstat_baseaddr {};
154: // アクセス状況が何ビット空間分か。NEWS だけ 30
155: uint accstat_bitlen {};
156:
157: // X68030 バンクメモリの表示用アクセス状況。
158: // (GUI からのアクセスの便宜のため共通クラスのこっちに置く)
159: alignas(8) uint8 accbank[AccStat::BANKLEN * 2] {};
160:
1.1.1.5 ! root 161: Monitor *accstat_monitor {};
1.1.1.3 root 162: };
163:
164: // 上位8ビットがテーブルで表せる構造のメインバス (共通部分)
165: class Mainbus24Device : public MainbusDevice
166: {
167: using inherited = MainbusDevice;
168: public:
169: Mainbus24Device();
170: ~Mainbus24Device() override;
171:
1.1.1.4 root 172: busdata Read(busaddr addr) override;
173: busdata Write(busaddr addr, uint32 data) override;
174: busdata ReadBurst16(busaddr addr, uint32 *dst) override;
175: busdata WriteBurst16(busaddr addr, const uint32 *src) override;
176: busdata Peek1(uint32 addr) override;
177: bool Poke1(uint32 addr, uint32 data) override;
1.1.1.3 root 178:
179: protected:
1.1.1.2 root 180: DECLARE_MONITOR_CALLBACK(MonitorUpdate);
1.1.1.3 root 181:
182: void InitAccStat();
183:
184: std::array<IODevice *, 256> devtable {};
185:
1.1.1.5 ! root 186: Monitor *monitor {};
1.1.1.3 root 187:
188: private:
189: inline IODevice *Decoder(uint32 addr) const;
1.1 root 190: };
191:
192: static inline MainbusDevice *GetMainbusDevice() {
193: return Object::GetObject<MainbusDevice>(OBJ_MAINBUS);
194: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.