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

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

unix.superglobalmegacorp.com

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