Annotation of nono/vm/test_busio.cpp, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.