--- nono/vm/bus.h 2026/04/29 17:05:33 1.1.1.8 +++ nono/vm/bus.h 2026/04/29 17:06:01 1.1.1.10 @@ -10,38 +10,45 @@ #pragma once -#include "nono.h" +#include "tick.h" // busaddr はアドレスバスにいくつかの情報を追加した構造。 // // : 6 : 5 : 4: 3:3 0 // 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-- ... --+ -// |B| |T|P| |Size | |R| |S|I|D|S| Address | -// |E| |S|A| | | |W| |U| | |U| (32bit) | +// |B| |C| |T|P| |Size | |R| |S|I|D|S| Address | +// |E| |I| |S|A| | | |W| |2| | | | (32bit) | // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-- ... --+ +// 7 6 5 4 3 2 1 0 +// BE (BusError, bit63) +// アドレス変換時のバスエラー。 // -// 32ビット目と35ビット目はどちらも S/U で同じ値を入れる。m68k の FC2 に相当。 -// 33ビット目は D (データ空間)。m68k の FC0 に相当。 -// 34ビット目は I (命令/プログラム空間)。m68k の FC1 に相当。 -// これにより、 -// o 下位 33 ビットで S/U と32ビットアドレスが表現できる。 -// o 下位 35 ビットで FC(順不同) と32ビットアドレスが表現できる。 -// o 上位ワードを >>1 すると下位3ビットが FC2-0 (同順) になる。 -// -// 39ビット目は R/W (Read なら 1)。これは SSW で使う。 -// 上位ワードを >>1 して下位 7 ビットを取り出すと SSW (の FC と R/W) になる。 -// -// 48,49,50ビット目は要求バイトサイズ (1 - 4)。 -// -// 63ビット目 (BE) は (アドレス変換時の) バスエラーを示す。 -// -// 以下はデバッガなどで使用する追加のビットで、実行系では使わない。 -// 56ビット目 (PA) はこのアドレスを物理アドレスとする場合は %1 を指定する。 -// 論理アドレスまたは区別が不要な場合は %0 にする。 -// 論理アドレスと物理アドレスの両方を受け取るメモリダンプとかで使う。 -// 57ビット目 (TS: Table Search Result) は、このアドレスを求めるのに -// テーブルサーチを行った場合は %1。 +// CI (Cache Inhibit, bit61) +// +// TS (Table Searched, bit57) +// このアドレスを求めるのにテーブルサーチを行ったら%1。デバッガアクセス用。 +// +// PA (Physical Address, bit56) +// このアドレスを物理アドレスとする場合は %1 を指定する。 +// 論理アドレスまたは区別が不要な場合は %0 にする。 +// 論理アドレスと物理アドレスの両方を受け取るメモリダンプとかで使う。 +// +// Size (bit50-48) +// 要求バイト数で 1 .. 4 で表す。 +// +// RW (Read/Write, bit39) +// Read なら %1。 +// 上位ワードを >>1 して下位7ビットを取り出すと SSW (の FC と RW) になる。 +// +// S2, I, D, S (bit35-32) +// S と S2 はどちらも S/U で同じ値を入れる。 +// D はデータアクセスなら %1 で、m68030 の FC0 に相当。 +// I は命令(プログラム)アクセスなら %1 で、m68030 の FC1 に相当。 +// この並びは +// o 下位 33 ビットで S/U と32ビットアドレスが表現できる。 +// o 下位 35 ビットで FC(順不同) と32ビットアドレスが表現できる。 +// o 上位ワードを >>1 すると下位3ビットが FC2-0 (同順) になる。 // 定数 enum class BusAddr : uint64 @@ -71,17 +78,18 @@ enum class BusAddr : uint64 Logical = 0x0000'0000'0000'0000ULL, TableSearched = 0x0200'0000'0000'0000ULL, + CInhibit = 0x2000'0000'0000'0000ULL, BusErr = 0x8000'0000'0000'0000ULL, }; // BusAddr に対する OR 演算子 (まだ busaddr は出せない) -static __unused BusAddr operator|(const BusAddr& lhs, const BusAddr& rhs) { +inline BusAddr operator|(const BusAddr& lhs, const BusAddr& rhs) { return (BusAddr)((uint64)lhs | (uint64)rhs); } -static __unused BusAddr operator|(const BusAddr& lhs, const uint64& rhs) { +inline BusAddr operator|(const BusAddr& lhs, const uint64& rhs) { return (BusAddr)((uint64)lhs | rhs); } -static __unused BusAddr operator|(const uint64& lhs, const BusAddr& rhs) { +inline BusAddr operator|(const uint64& lhs, const BusAddr& rhs) { return (BusAddr)(lhs | (uint64)rhs); } @@ -112,6 +120,7 @@ class busaddr value = value_; } + // enum からの自動変換のため explicit つけない。 busaddr(BusAddr value_) noexcept { value = (uint64)value_; } @@ -128,16 +137,18 @@ class busaddr uint64 GetSAddr() const noexcept { return value & 0x1'ffff'ffffULL; } uint32 GetFC() const noexcept { return (value >> 33) & 7; } - uint32 GetSSW() const noexcept { return (value >> 33) & 0x47; } uint32 GetSize() const noexcept { return (value >> 48) & 7; } bool IsSuper() const noexcept { return (value & (uint64)BusAddr::S); } bool IsData() const noexcept { return (value & (uint64)BusAddr::D); } - bool IsWrite() const noexcept - { return (value & (uint64)BusAddr::R) == 0; } + bool IsRead() const noexcept { return (value & (uint64)BusAddr::R); } + bool IsWrite() const noexcept { return !IsRead(); } bool IsPhysical() const noexcept { return (value & (uint64)BusAddr::Physical); } bool IsTableSearched() const noexcept { return (value & (uint64)BusAddr::TableSearched); } + bool IsCInhibit() const noexcept + { return (value & (uint64)BusAddr::CInhibit); } + bool IsOK() const noexcept { return !IsBusErr(); } bool IsBusErr() const noexcept { return (value & (uint64)BusAddr::BusErr); } @@ -225,24 +236,24 @@ class busaddr }; // busaddr の等価演算子 -static __unused bool operator==(const busaddr& lhs, const busaddr& rhs) { +inline bool operator==(const busaddr& lhs, const busaddr& rhs) { return (lhs.Get() == rhs.Get()); } -static __unused bool operator!=(const busaddr& lhs, const busaddr& rhs) { +inline bool operator!=(const busaddr& lhs, const busaddr& rhs) { return !(lhs == rhs); } // busaddr に対する OR 演算子 -static __unused busaddr operator|(const busaddr& lhs, const uint64& rhs) { +inline busaddr operator|(const busaddr& lhs, const uint64& rhs) { return busaddr(lhs.Get() | rhs); } -static __unused busaddr operator|(const busaddr& lhs, const busaddr& rhs) { +inline busaddr operator|(const busaddr& lhs, const busaddr& rhs) { return lhs | rhs.Get(); } -static __unused busaddr operator|(const busaddr& lhs, const BusAddr& rhs) { +inline busaddr operator|(const busaddr& lhs, const BusAddr& rhs) { return lhs | (busaddr)rhs; } -static __unused busaddr operator|(const BusAddr& lhs, const busaddr& rhs) { +inline busaddr operator|(const BusAddr& lhs, const busaddr& rhs) { return (busaddr)lhs | rhs; } @@ -256,9 +267,18 @@ static __unused busaddr operator|(const // |E|T| | | | (32bit) | // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-- ... --+ // -// BE (63ビット目) はバスエラー。 -// RT (62ビット目) はリトライ。SPC で使う。 -// 48,49,50ビット目は応答サイズ。デバイスが処理したバイト数を 1 - 4 で返す。 +// BE (BusError, bit63) +// バスエラー。 +// +// RT (Retry, bit62) +// リトライ。SPC で使う。 +// +// Size (bit50-48) +// デバイスが処理したバイト数で、1 .. 4 で表す。 +// +// Wait (bit47-32) +// ウェイトは [tsec] で設定・取得するが、ここに格納するときは [nsec] にする。 +// XXX あとで Size を移動してから [tsec] に統一するかも。 // 定数 enum class BusData : uint64 @@ -276,13 +296,13 @@ enum class BusData : uint64 }; // BusData に対する OR 演算子 (まだ busdata は出せない) -static __unused BusData operator|(const BusData& lhs, const BusData& rhs) { +inline BusData operator|(const BusData& lhs, const BusData& rhs) { return (BusData)((uint64)lhs | (uint64)rhs); } -static __unused BusData operator|(const BusData& lhs, const uint64& rhs) { +inline BusData operator|(const BusData& lhs, const uint64& rhs) { return (BusData)((uint64)lhs | rhs); } -static __unused BusData operator|(const uint64& lhs, const BusData& rhs) { +inline BusData operator|(const uint64& lhs, const BusData& rhs) { return (BusData)(lhs | (uint64)rhs); } @@ -292,9 +312,9 @@ class busdata uint64 value {}; public: - // ウェイト - static constexpr BusData Wait(uint32 nsec) noexcept { - return (BusData)((uint64)nsec << 32); + // ウェイトを [tsec] で指定する + static constexpr BusData Wait(uint64 tsec) noexcept { + return (BusData)(tsec_to_nsec(tsec) << 32); } // データサイズ static constexpr BusData Size(uint n) noexcept { @@ -318,6 +338,7 @@ class busdata value = value_; } + // enum からの自動変換のため explicit つけない。 busdata(BusData value_) noexcept { value = (uint64)value_; } @@ -333,7 +354,10 @@ class busdata uint32 GetH() const noexcept { return (uint32)(value >> 32); } uint32 GetL() const noexcept { return (uint32)value; } uint32 Data() const noexcept { return (uint32)value; } - uint32 GetWait() const noexcept { return (uint32)((value >> 32) & 0xffff); } + // ウェイトを [tsec] で取得。 + uint64 GetWait() const noexcept { + return nsec_to_tsec((value >> 32) & 0xffff); + } uint32 GetSize() const noexcept { return (uint32)((value >> 48) & 7); } bool IsOK() const noexcept { return (value & Mask) == 0; } bool IsBusErr() const noexcept { return (value & BusErrBit); } @@ -343,9 +367,10 @@ class busdata value &= 0xffffffff'00000000; value |= data_; } - void ChangeWait(uint32 wait) noexcept { + // ウェイトを tsec に変更。 + void ChangeWait(uint64 tsec) noexcept { value &= 0xffff0000'ffffffff; - value |= (uint64)Wait(wait); + value |= (uint64)Wait(tsec); } void ChangeSize(uint32 n) noexcept { value &= ~(uint64)BusData::SizeMask; @@ -381,18 +406,18 @@ class busdata }; // busdata に対する OR 演算子 -static __unused busdata operator|(const busdata& lhs, const uint64& rhs) { +inline busdata operator|(const busdata& lhs, const uint64& rhs) { return busdata(lhs.Get() | rhs); } -static __unused busdata operator|(const busdata& lhs, const busdata& rhs) { +inline busdata operator|(const busdata& lhs, const busdata& rhs) { return lhs | rhs.Get(); } -static __unused busdata operator|(const busdata& lhs, const BusData& rhs) { +inline busdata operator|(const busdata& lhs, const BusData& rhs) { return lhs | (busdata)rhs; } -static __unused busdata operator|(const BusData& lhs, const busdata& rhs) { +inline busdata operator|(const BusData& lhs, const busdata& rhs) { return (busdata)lhs | rhs; } -static __unused busdata operator|(const uint64& lhs, const busdata& rhs) { +inline busdata operator|(const uint64& lhs, const busdata& rhs) { return busdata(lhs | rhs.Get()); }