--- nono/vm/mainbus.h 2026/04/29 17:05:25 1.1.1.3 +++ nono/vm/mainbus.h 2026/04/29 17:05:50 1.1.1.6 @@ -12,7 +12,7 @@ #include "device.h" #include "bus.h" -#include "monitor.h" +#include "textscreen.h" #include #include @@ -21,7 +21,7 @@ class MainbusBaseDevice : public IODevic { using inherited = IODevice; public: - MainbusBaseDevice(int objid_); + explicit MainbusBaseDevice(uint objid_); ~MainbusBaseDevice() override; // メインバスの初期化 @@ -30,22 +30,6 @@ class MainbusBaseDevice : public IODevic // MPU からのリセット (ここ?) virtual void ResetByMPU(); - // addr 版 (こっちは呼ばないこと) - busdata Read8(uint32 addr) override final; - busdata Read16(uint32 addr) override final; - busdata Read32(uint32 addr) override final; - busdata Write8(uint32 addr, uint32 data) override final; - busdata Write16(uint32 addr, uint32 data) override final; - busdata Write32(uint32 addr, uint32 data) override final; - - // busaddr 版 - virtual busdata Read8(busaddr addr) = 0; - virtual busdata Read16(busaddr addr) = 0; - virtual busdata Read32(busaddr addr) = 0; - virtual busdata Write8(busaddr addr, uint32 data) = 0; - virtual busdata Write16(busaddr addr, uint32 data) = 0; - virtual busdata Write32(busaddr addr, uint32 data) = 0; - // ブートページを ROM に切り替える void SwitchBootPageToROM() { SwitchBootPage(true); } // ブートページを RAM に切り替える @@ -59,29 +43,122 @@ class MainbusBaseDevice : public IODevic virtual void SwitchBootPage(bool isrom) = 0; }; +// 定数クラス。本当はインタフェースっぽくしたい +class AccStat +{ + public: + // アクセス状況を記録・表示する際に切り捨てる下位ビット数 + static const uint SHIFT = 21; + + // メイン空間とバンクメモリ(1枚分)の要素数 + static const uint MAINLEN = (1U << (32 - SHIFT)); + static const uint BANKLEN = (1U << (24 - SHIFT)); + + // アクセス状況 + static const uint8 WRITE = 0x01; + static const uint8 READ = 0x02; +}; + // メインバス (システムに1つ) class MainbusDevice : public MainbusBaseDevice { using inherited = MainbusBaseDevice; + friend class WXAccStatPanel; + public: - // アクセス状況 (詳細は機種ごと) - static const uint8 ACC_READ = 0x01; - static const uint8 ACC_WRITE = 0x02; + // ダイナミックバスサイジング処理用のマクロっぽい関数。 + // 使い方は HVReadN()、HVWriteN() を参照。 + + // 読み込み後の処理。 + // addr は読み込みに使ったアドレス、bd は読み込んだデータ。 + // 次の読み込み用にアドレスとサイズを更新して addr に書き戻す。 + static inline uint32 + DYNAMIC_BUS_SIZING_R(busaddr& addr, busdata bd) + { + uint32 reqsize = addr.GetSize(); + uint32 portsize = bd.GetSize(); + uint32 offset = addr.Addr() & (portsize - 1); + uint32 datasize = portsize - offset; + uint32 tmp = bd.Data(); + uint32 mask = 0xffffffffU >> ((4 - datasize) * 8); + tmp &= mask; + if (datasize == reqsize) { + addr += reqsize; + addr.ChangeSize(0); + } else if (datasize > reqsize) { + tmp >>= (datasize - reqsize) * 8; + addr += reqsize; + addr.ChangeSize(0); + } else { + tmp <<= (reqsize - datasize) * 8; + addr += datasize; + addr.ChangeSize(reqsize - datasize); + } + + // 今回読み出した値を所定の位置に左シフトしたものを返す。 + return tmp; + } + + // 書き込み後の処理部分。 + // addr、data は書き込みに使ったアドレスとデータ。r が書き込みの応答。 + // 次の書き込み用に、addr はアドレスとサイズを更新したもの、 + // data も使い終わった上位バイトをクリアしたものを書き戻す。 + static inline void + DYNAMIC_BUS_SIZING_W(busaddr& addr, uint32& data, busdata r) + { + uint32 reqsize = addr.GetSize(); + uint32 portsize = r.GetSize(); + uint32 offset = addr.Addr() & (portsize - 1); + uint32 datasize = std::min(portsize - offset, reqsize); + + addr += datasize; + reqsize -= datasize; + addr.ChangeSize(reqsize); + data &= (1U << (reqsize * 8)) - 1; + } public: - MainbusDevice(int objid_); + explicit MainbusDevice(uint objid_); ~MainbusDevice() override; + bool Init() override; + void ResetHard(bool poweron) override; + // ハイパーバイザ的アクセスというか、 // 今となってはミスアライン可能なアクセスというだけかも知れない。 - busdata HVRead8(uint32 addr); - busdata HVRead16(uint32 addr); - busdata HVRead32(uint32 addr); - busdata HVWrite8(uint32 addr, uint32 data); - busdata HVWrite16(uint32 addr, uint32 data); - busdata HVWrite32(uint32 addr, uint32 data); + busdata HVRead1(uint32 addr); + busdata HVRead2(uint32 addr); + busdata HVRead4(uint32 addr); + busdata HVWrite1(uint32 addr, uint32 data); + busdata HVWrite2(uint32 addr, uint32 data); + busdata HVWrite4(uint32 addr, uint32 data); + // サイズを addr で指定する版 + busdata HVReadN(busaddr addr); + busdata HVWriteN(busaddr addr, uint32 data); + + uint64 Peek4(uint32 addr); - uint64 Peek32(uint32 addr); + protected: + DECLARE_MONITOR_CALLBACK(MonitorUpdateAccStat); + + // アクセス状況は 32bit 空間全域を 2048 * 2MB ずつ。 + // (NEWS は読み出し時にマージする) + std::array accstat_read {}; + std::array accstat_write {}; + // R, W をマージした表示用(要素数は機種による) + std::vector accstat_rw {}; + // デバイスの存在有無。MSB 側から 1bit = 16MB のビットマップ。 + std::array accstat_avail {}; + // アクセス状況のアドレス表示オフセット。NEWS だけ 0xc0 + uint accstat_baseaddr {}; + // アクセス状況が何ビット空間分か。NEWS だけ 30 + uint accstat_bitlen {}; + + // X68030 バンクメモリの表示用アクセス状況。 + // (GUI からのアクセスの便宜のため共通クラスのこっちに置く) + alignas(8) uint8 accbank[AccStat::BANKLEN * 2] {}; + + Monitor *accstat_monitor {}; }; // 上位8ビットがテーブルで表せる構造のメインバス (共通部分) @@ -92,36 +169,21 @@ class Mainbus24Device : public MainbusDe Mainbus24Device(); ~Mainbus24Device() override; - void ResetHard(bool poweron) override; - - busdata Read8(busaddr addr) override; - busdata Read16(busaddr addr) override; - busdata Read32(busaddr addr) override; - busdata Write8(busaddr addr, uint32 data) override; - busdata Write16(busaddr addr, uint32 data) override; - busdata Write32(busaddr addr, uint32 data) override; - busdata Peek8(uint32 addr) override; - bool Poke8(uint32 addr, uint32 data) override; + busdata Read(busaddr addr) override; + busdata Write(busaddr addr, uint32 data) override; + busdata ReadBurst16(busaddr addr, uint32 *dst) override; + busdata WriteBurst16(busaddr addr, const uint32 *src) override; + busdata Peek1(uint32 addr) override; + bool Poke1(uint32 addr, uint32 data) override; protected: DECLARE_MONITOR_CALLBACK(MonitorUpdate); - DECLARE_MONITOR_CALLBACK(MonitorUpdateAccStat); void InitAccStat(); std::array devtable {}; - // アクセス状況は 32bit 空間全域を 2048 * 2MB ずつ。 - // (NEWS は読み出し時にマージする) - std::array accstat_read {}; - std::array accstat_write {}; - // 表示エリア - std::array accstat_area {}; - // 表示用(要素数は機種による) - std::vector acc {}; - - Monitor monitor { this }; - Monitor monitor_accstat { this }; + Monitor *monitor {}; private: inline IODevice *Decoder(uint32 addr) const;