|
|
1.1 ! root 1: #include "header.h" ! 2: #include <stdint.h> ! 3: #include <vector> ! 4: ! 5: // "device.h" の IODevice をリンクしてしまうと、芋づる式に依存オブジェクトが ! 6: // 増えてしまい収拾つかなくなるので、ダミークラスを用意する。 ! 7: // なので、ここの実装は本物の IODevice のそれと同期しないといけない…。 ! 8: class IODevice ! 9: { ! 10: public: ! 11: IODevice() {} ! 12: virtual ~IODevice() {} ! 13: ! 14: virtual uint64 Read8(uint32 addr) { return 0xef; } ! 15: virtual uint64 Read16(uint32 addr) { ! 16: return (Read8(addr) << 8) | (Read8(addr + 1)); ! 17: } ! 18: virtual uint64 Read32(uint32 addr) { ! 19: return (Read16(addr) << 16) | (Read16(addr + 2)); ! 20: } ! 21: virtual uint64 Write8(uint32 addr, uint32 data) { return 0; } ! 22: virtual uint64 Write16(uint32 addr, uint32 data) { ! 23: uint64 r; ! 24: r = Write8(addr, data >> 8); ! 25: r |= Write8(addr + 1, data & 0xff); ! 26: return r; ! 27: } ! 28: virtual uint64 Write32(uint32 addr, uint32 data) { ! 29: uint64 r; ! 30: r = Write16(addr, data >> 16); ! 31: r |= Write16(addr + 2, data & 0xffff); ! 32: return r; ! 33: } ! 34: virtual uint64 Peek8(uint32 addr) { return 0xff; } ! 35: }; ! 36: ! 37: #define SELFTEST ! 38: #include "busio.h" ! 39: ! 40: class TestByteDev : public IODevice ! 41: { ! 42: public: ! 43: TestByteDev() {} ! 44: virtual ~TestByteDev() {} ! 45: ! 46: static const uint32 NPORT = 4; ! 47: uint32 reg[NPORT] {}; ! 48: uint64 Read(uint32 addr) { ! 49: if ((int32)reg[addr] < 0) ! 50: return (uint64)-1; ! 51: return reg[addr]; ! 52: } ! 53: uint64 Write(uint32 addr, uint32 data) { ! 54: reg[addr] = data; ! 55: return 0; ! 56: } ! 57: uint64 Peek(uint32 addr) { ! 58: if ((int32)reg[addr] < 0) ! 59: return (uint64)-1; ! 60: return reg[addr]; ! 61: } ! 62: }; ! 63: ! 64: class TestWordDev : public IODevice ! 65: { ! 66: public: ! 67: TestWordDev() {} ! 68: virtual ~TestWordDev() {} ! 69: ! 70: static const uint32 NPORT = 4; ! 71: uint32 reg[NPORT] {}; ! 72: uint64 Read(uint32 addr) { ! 73: if ((int32)reg[addr] < 0) ! 74: return (uint64)-1; ! 75: return reg[addr]; ! 76: } ! 77: uint64 Write(uint32 addr, uint32 data) { ! 78: reg[addr] = data; ! 79: return 0; ! 80: } ! 81: uint64 Peek(uint32 addr) { ! 82: if ((int32)reg[addr] < 0) ! 83: return (uint64)-1; ! 84: return reg[addr]; ! 85: } ! 86: }; ! 87: ! 88: // テストデータ ! 89: // expected[] の1エントリは1バイトを表す(WordDevの時も同様)。 ! 90: #define E ((uint64)-1) ! 91: #define F (0xff) ! 92: struct testdata { ! 93: const char *name; ! 94: std::vector<uint64> expected; ! 95: } testdata_b[] = { ! 96: { "BusIO_B", { ! 97: 1, 2, 3, 4, 1, 2, 3, 4, ! 98: } }, ! 99: { "BusIO_BB", { ! 100: 1, 1, 2, 2, 3, 3, 4, 4, 1, 1, 2, 2, 3, 3, 4, 4, ! 101: } }, ! 102: { "BusIO_BBBB", { ! 103: 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, ! 104: 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, ! 105: } }, ! 106: { "BusIO_BE", { ! 107: 1, E, 2, E, 3, E, 4, E, 1, E, 2, E, 3, E, 4, E, ! 108: } }, ! 109: { "BusIO_EB", { ! 110: E, 1, E, 2, E, 3, E, 4, E, 1, E, 2, E, 3, E, 4, ! 111: } }, ! 112: { "BusIO_BFFF", { ! 113: 1, F, F, F, 2, F, F, F, 3, F, F, F, 4, F, F, F, ! 114: 1, F, F, F, 2, F, F, F, 3, F, F, F, 4, F, F, F, ! 115: } }, ! 116: }, testdata_w[] = { ! 117: { "BusIO_W", { ! 118: 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, ! 119: } }, ! 120: { "BusIO_WW", { ! 121: 1, 2, 1, 2, 3, 4, 3, 4, 5, 6, 5, 6, 7, 8, 7, 8, ! 122: 1, 2, 1, 2, 3, 4, 3, 4, 5, 6, 5, 6, 7, 8, 7, 8, ! 123: } }, ! 124: { "BusIO_WF", { ! 125: 1, 2, F, F, 3, 4, F, F, 5, 6, F, F, 7, 8, F, F, ! 126: 1, 2, F, F, 3, 4, F, F, 5, 6, F, F, 7, 8, F, F, ! 127: } }, ! 128: }; ! 129: ! 130: void fail(const char *fmt, ...) __printflike(1, 2); ! 131: void ! 132: fail(const char *fmt, ...) ! 133: { ! 134: va_list ap; ! 135: ! 136: printf(" FAIL: "); ! 137: va_start(ap, fmt); ! 138: vprintf(fmt, ap); ! 139: va_end(ap); ! 140: } ! 141: ! 142: template<typename T> void ! 143: do_test(struct testdata *test, T *dev) ! 144: { ! 145: printf("%s\n", test->name); ! 146: ! 147: // デバイス側に読み出し元データをセット。 ! 148: // 元データは常にバイト単位で列挙してあるので、ターゲットデバイスの ! 149: // サイズによってセット方法が変わる。 ! 150: if (dynamic_cast<TestByteDev*>(dev)) { ! 151: for (int i = 0; i < dev->NPORT; i++) { ! 152: dev->reg[i] = (i + 1); ! 153: } ! 154: } else { ! 155: for (int i = 0, j = 0; i < dev->NPORT; i++) { ! 156: uint32 data; ! 157: data = (++j) << 8; ! 158: data |= (++j); ! 159: dev->reg[i] = data; ! 160: } ! 161: } ! 162: ! 163: // Read8 のテスト ! 164: for (int i = 0; i < test->expected.size(); i++) { ! 165: uint64 act = dev->Read8(i); ! 166: uint64 exp = test->expected[i]; ! 167: if (act != exp) { ! 168: fail("%s::Read8(%d) expects %02" PRIx64 " but %02" PRIx64 "\n", ! 169: test->name, i, exp, act); ! 170: } ! 171: } ! 172: // Read16 のテスト ! 173: for (int i = 0; i < test->expected.size(); i += 2) { ! 174: uint64 act = dev->Read16(i); ! 175: uint64 e0 = test->expected[i + 0]; ! 176: uint64 e1 = test->expected[i + 1]; ! 177: uint64 exp; ! 178: if ((int64)e0 < 0 && (int64)e1 < 0) { ! 179: // 両方バスエラーならバスエラー? ! 180: exp = (int64)-1; ! 181: } else { ! 182: // そうでなければバスエラー側は 0xff ? ! 183: exp = (((uint8)e0) << 8) | ((uint8)e1); ! 184: } ! 185: if (act != exp) { ! 186: fail("%s::Read16(%d) expects %04" PRIx64 " but %04" PRIx64 "\n", ! 187: test->name, i, exp, act); ! 188: } ! 189: } ! 190: // Read32 のテスト ! 191: for (int i = 0; i < test->expected.size(); i += 4) { ! 192: uint64 act = dev->Read32(i); ! 193: uint64 e0 = test->expected[i + 0]; ! 194: uint64 e1 = test->expected[i + 1]; ! 195: uint64 e2 = test->expected[i + 2]; ! 196: uint64 e3 = test->expected[i + 3]; ! 197: uint64 exp; ! 198: if ((int64)e0 < 0 && (int64)e1 < 0 && (int64)e2 < 0 && (int64)e3 < 0) { ! 199: // 全部バスエラーならバスエラー? ! 200: exp = (int64)-1; ! 201: } else { ! 202: // そうでなければバスエラー部分だけ 0xff ? ! 203: e0 = (uint8)e0 << 24; ! 204: e1 = (uint8)e1 << 16; ! 205: e2 = (uint8)e2 << 8; ! 206: e3 = (uint8)e3; ! 207: exp = (uint64)(uint32)(e0 | e1 | e2 | e3); ! 208: } ! 209: if (act != exp) { ! 210: fail("%s::Read32(%d) expects %08" PRIx64 " but %08" PRIx64 "\n", ! 211: test->name, i, exp, act); ! 212: } ! 213: } ! 214: // Peek8 のテスト ! 215: for (int i = 0; i < test->expected.size(); i++) { ! 216: uint64 act = dev->Peek8(i); ! 217: uint64 exp = test->expected[i]; ! 218: if (act != exp) { ! 219: fail("%s::Peek8(%d) expects %02" PRIx64 " but %02" PRIx64 "\n", ! 220: test->name, i, exp, act); ! 221: } ! 222: } ! 223: ! 224: // Write 系のテストはちょっと保留。 ! 225: } ! 226: ! 227: int ! 228: main() ! 229: { ! 230: do_test<TestByteDev>(&testdata_b[0], new BusIO_B<TestByteDev>()); ! 231: do_test<TestByteDev>(&testdata_b[1], new BusIO_BB<TestByteDev>()); ! 232: do_test<TestByteDev>(&testdata_b[2], new BusIO_BBBB<TestByteDev>()); ! 233: do_test<TestByteDev>(&testdata_b[3], new BusIO_BE<TestByteDev>()); ! 234: do_test<TestByteDev>(&testdata_b[4], new BusIO_EB<TestByteDev>()); ! 235: do_test<TestByteDev>(&testdata_b[5], new BusIO_BFFF<TestByteDev>()); ! 236: ! 237: do_test<TestWordDev>(&testdata_w[0], new BusIO_W<TestWordDev>()); ! 238: do_test<TestWordDev>(&testdata_w[1], new BusIO_WW<TestWordDev>()); ! 239: do_test<TestWordDev>(&testdata_w[2], new BusIO_WF<TestWordDev>()); ! 240: return 0; ! 241: } ! 242: ! 243: // リンカを通すためのダミー ! 244: void ! 245: panic(const char *funcname, const char *fmt, ...) ! 246: { ! 247: va_list ap; ! 248: ! 249: printf("panic: %s: ", funcname); ! 250: va_start(ap, fmt); ! 251: vprintf(fmt, ap); ! 252: va_end(ap); ! 253: exit(1); ! 254: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.