|
|
1.1.1.2 root 1: //
2: // nono
3: // Copyright (C) 2020 nono project
4: // Licensed under nono-license.txt
5: //
6:
1.1 root 7: #include "header.h"
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:
20: virtual uint64 Read8(uint32 addr) { return 0xef; }
21: virtual uint64 Read16(uint32 addr) {
22: return (Read8(addr) << 8) | (Read8(addr + 1));
23: }
24: virtual uint64 Read32(uint32 addr) {
25: return (Read16(addr) << 16) | (Read16(addr + 2));
26: }
27: virtual uint64 Write8(uint32 addr, uint32 data) { return 0; }
28: virtual uint64 Write16(uint32 addr, uint32 data) {
29: uint64 r;
30: r = Write8(addr, data >> 8);
31: r |= Write8(addr + 1, data & 0xff);
32: return r;
33: }
34: virtual uint64 Write32(uint32 addr, uint32 data) {
35: uint64 r;
36: r = Write16(addr, data >> 16);
37: r |= Write16(addr + 2, data & 0xffff);
38: return r;
39: }
40: virtual uint64 Peek8(uint32 addr) { return 0xff; }
1.1.1.5 ! root 41: virtual uint64 Poke8(uint32 addr, uint32 data) { return (uint64)-1; }
! 42: virtual uint64 Poke(uint32 addr, uint32 data) { return (uint64)-1; }
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] {};
57: uint64 Read(uint32 addr) {
58: if ((int32)reg[addr] < 0)
59: return (uint64)-1;
60: return reg[addr];
61: }
62: uint64 Write(uint32 addr, uint32 data) {
63: reg[addr] = data;
64: return 0;
65: }
66: uint64 Peek(uint32 addr) {
67: if ((int32)reg[addr] < 0)
68: return (uint64)-1;
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] {};
82: uint64 Read(uint32 addr) {
83: if ((int32)reg[addr] < 0)
84: return (uint64)-1;
85: return reg[addr];
86: }
87: uint64 Write(uint32 addr, uint32 data) {
88: reg[addr] = data;
89: return 0;
90: }
91: uint64 Peek(uint32 addr) {
92: if ((int32)reg[addr] < 0)
93: return (uint64)-1;
94: return reg[addr];
95: }
96: };
1.1.1.3 root 97: TestWordDev::~TestWordDev() { }
1.1 root 98:
99: // テストデータ
100: // expected[] の1エントリは1バイトを表す(WordDevの時も同様)。
101: #define E ((uint64)-1)
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_WW", {
135: 1, 2, 1, 2, 3, 4, 3, 4, 5, 6, 5, 6, 7, 8, 7, 8,
136: 1, 2, 1, 2, 3, 4, 3, 4, 5, 6, 5, 6, 7, 8, 7, 8,
137: } },
138: { "BusIO_WF", {
139: 1, 2, F, F, 3, 4, F, F, 5, 6, F, F, 7, 8, F, F,
140: 1, 2, F, F, 3, 4, F, F, 5, 6, F, F, 7, 8, F, F,
141: } },
142: };
143:
144: void fail(const char *fmt, ...) __printflike(1, 2);
145: void
146: fail(const char *fmt, ...)
147: {
148: va_list ap;
149:
150: printf(" FAIL: ");
151: va_start(ap, fmt);
152: vprintf(fmt, ap);
153: va_end(ap);
154: }
155:
156: template<typename T> void
157: do_test(struct testdata *test, T *dev)
158: {
159: printf("%s\n", test->name);
160:
161: // デバイス側に読み出し元データをセット。
162: // 元データは常にバイト単位で列挙してあるので、ターゲットデバイスの
163: // サイズによってセット方法が変わる。
164: if (dynamic_cast<TestByteDev*>(dev)) {
165: for (int i = 0; i < dev->NPORT; i++) {
166: dev->reg[i] = (i + 1);
167: }
168: } else {
169: for (int i = 0, j = 0; i < dev->NPORT; i++) {
170: uint32 data;
171: data = (++j) << 8;
172: data |= (++j);
173: dev->reg[i] = data;
174: }
175: }
176:
177: // Read8 のテスト
178: for (int i = 0; i < test->expected.size(); i++) {
179: uint64 act = dev->Read8(i);
180: uint64 exp = test->expected[i];
181: if (act != exp) {
182: fail("%s::Read8(%d) expects %02" PRIx64 " but %02" PRIx64 "\n",
183: test->name, i, exp, act);
184: }
185: }
186: // Read16 のテスト
187: for (int i = 0; i < test->expected.size(); i += 2) {
188: uint64 act = dev->Read16(i);
189: uint64 e0 = test->expected[i + 0];
190: uint64 e1 = test->expected[i + 1];
191: uint64 exp;
192: if ((int64)e0 < 0 && (int64)e1 < 0) {
193: // 両方バスエラーならバスエラー?
194: exp = (int64)-1;
195: } else {
196: // そうでなければバスエラー側は 0xff ?
197: exp = (((uint8)e0) << 8) | ((uint8)e1);
198: }
199: if (act != exp) {
200: fail("%s::Read16(%d) expects %04" PRIx64 " but %04" PRIx64 "\n",
201: test->name, i, exp, act);
202: }
203: }
204: // Read32 のテスト
205: for (int i = 0; i < test->expected.size(); i += 4) {
206: uint64 act = dev->Read32(i);
207: uint64 e0 = test->expected[i + 0];
208: uint64 e1 = test->expected[i + 1];
209: uint64 e2 = test->expected[i + 2];
210: uint64 e3 = test->expected[i + 3];
211: uint64 exp;
212: if ((int64)e0 < 0 && (int64)e1 < 0 && (int64)e2 < 0 && (int64)e3 < 0) {
213: // 全部バスエラーならバスエラー?
214: exp = (int64)-1;
215: } else {
216: // そうでなければバスエラー部分だけ 0xff ?
217: e0 = (uint8)e0 << 24;
218: e1 = (uint8)e1 << 16;
219: e2 = (uint8)e2 << 8;
220: e3 = (uint8)e3;
221: exp = (uint64)(uint32)(e0 | e1 | e2 | e3);
222: }
223: if (act != exp) {
224: fail("%s::Read32(%d) expects %08" PRIx64 " but %08" PRIx64 "\n",
225: test->name, i, exp, act);
226: }
227: }
228: // Peek8 のテスト
229: for (int i = 0; i < test->expected.size(); i++) {
230: uint64 act = dev->Peek8(i);
231: uint64 exp = test->expected[i];
232: if (act != exp) {
233: fail("%s::Peek8(%d) expects %02" PRIx64 " but %02" PRIx64 "\n",
234: test->name, i, exp, act);
235: }
236: }
237:
238: // Write 系のテストはちょっと保留。
239: }
240:
241: int
242: main()
243: {
244: do_test<TestByteDev>(&testdata_b[0], new BusIO_B<TestByteDev>());
245: do_test<TestByteDev>(&testdata_b[1], new BusIO_BB<TestByteDev>());
246: do_test<TestByteDev>(&testdata_b[2], new BusIO_BBBB<TestByteDev>());
247: do_test<TestByteDev>(&testdata_b[3], new BusIO_BE<TestByteDev>());
248: do_test<TestByteDev>(&testdata_b[4], new BusIO_EB<TestByteDev>());
1.1.1.2 root 249: do_test<TestByteDev>(&testdata_b[5], new BusIO_FB<TestByteDev>());
250: do_test<TestByteDev>(&testdata_b[6], new BusIO_BFFF<TestByteDev>());
1.1 root 251:
252: do_test<TestWordDev>(&testdata_w[0], new BusIO_W<TestWordDev>());
253: do_test<TestWordDev>(&testdata_w[1], new BusIO_WW<TestWordDev>());
254: do_test<TestWordDev>(&testdata_w[2], new BusIO_WF<TestWordDev>());
255: return 0;
256: }
257:
258: // リンカを通すためのダミー
259: void
1.1.1.5 ! root 260: vmpanic_func(const char *funcname, const char *fmt, ...)
1.1 root 261: {
262: va_list ap;
263:
264: printf("panic: %s: ", funcname);
265: va_start(ap, fmt);
266: vprintf(fmt, ap);
267: va_end(ap);
268: exit(1);
269: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.