|
|
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.