Annotation of nono/vm/test_busio.cpp, revision 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.