OpenCores
URL https://opencores.org/ocsvn/s80186/s80186/trunk

Subversion Repositories s80186

[/] [s80186/] [trunk/] [tests/] [rtl/] [TestPIC.cpp] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 jamieiles
// Copyright Jamie Iles, 2017
2
//
3
// This file is part of s80x86.
4
//
5
// s80x86 is free software: you can redistribute it and/or modify
6
// it under the terms of the GNU General Public License as published by
7
// the Free Software Foundation, either version 3 of the License, or
8
// (at your option) any later version.
9
//
10
// s80x86 is distributed in the hope that it will be useful,
11
// but WITHOUT ANY WARRANTY; without even the implied warranty of
12
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
// GNU General Public License for more details.
14
//
15
// You should have received a copy of the GNU General Public License
16
// along with s80x86.  If not, see <http://www.gnu.org/licenses/>.
17
 
18
#include <stdexcept>
19
#include <deque>
20
#include <VPIC.h>
21
#include "VerilogTestbench.h"
22
 
23
class PICTestBench : public VerilogTestbench<VPIC>, public ::testing::Test
24
{
25
public:
26
    PICTestBench()
27
    {
28
        reset();
29
    }
30
 
31
protected:
32
    uint8_t access(int offs, bool write = false, uint8_t wr_val = 0)
33
    {
34
        uint16_t v;
35
 
36
        after_n_cycles(0, [this, &v, offs, wr_val, write] {
37
            this->dut.cs = 1;
38
            this->dut.data_m_data_in = static_cast<uint16_t>(wr_val)
39
                                       << (offs * 8);
40
            this->dut.data_m_bytesel = 1 << offs;
41
            this->dut.data_m_wr_en = write;
42
            this->dut.data_m_access = 1;
43
 
44
            after_n_cycles(1, [this, &v] {
45
                this->dut.cs = 0;
46
                this->dut.data_m_access = 0;
47
                v = this->dut.data_m_data_out;
48
            });
49
        });
50
 
51
        this->cycle(2);
52
 
53
        return v >> (offs * 8);
54
    }
55
 
56
    void write_reg(int offs, uint8_t v)
57
    {
58
        access(offs, true, v);
59
    }
60
 
61
    uint8_t read_reg(int offs)
62
    {
63
        return access(offs);
64
    }
65
 
66
    uint8_t read_irr()
67
    {
68
        write_reg(0, 0x0a);
69
 
70
        return read_reg(0);
71
    }
72
 
73
    uint8_t read_isr()
74
    {
75
        write_reg(0, 0x0b);
76
 
77
        return read_reg(0);
78
    }
79
 
80
    void set_mask(uint8_t v)
81
    {
82
        write_reg(1, v);
83
    }
84
 
85
    void setup_watch_and_ack()
86
    {
87
        periodic(ClockSetup, [this] {
88
            if (this->dut.intr) {
89
                after_n_cycles(0, [this] {
90
                    this->dut.inta = 1;
91
                    irqs_taken.push_back(this->dut.irq);
92
                    after_n_cycles(1, [this] {
93
                        this->dut.inta = 0;
94
                        this->dut.intr_in &=
95
                            ~(1 << ((*std::prev(irqs_taken.end())) - 8));
96
                    });
97
                });
98
            }
99
        });
100
    }
101
 
102
    std::deque<int> irqs_taken;
103
};
104
 
105
TEST_F(PICTestBench, Init)
106
{
107
    write_reg(0, 0x13);
108
    write_reg(1, 0x08);
109
    write_reg(1, 0x01);
110
 
111
    this->cycle(8);
112
 
113
    ASSERT_FALSE(this->dut.intr);
114
    ASSERT_EQ(this->dut.irq, 0);
115
}
116
 
117
TEST_F(PICTestBench, IRQVector)
118
{
119
    write_reg(0, 0x13);
120
    write_reg(1, 0x08);
121
    write_reg(1, 0x01);
122
 
123
    set_mask(0x00);
124
 
125
    this->cycle(2);
126
    this->dut.intr_in = (1 << 3);
127
    this->cycle(2);
128
 
129
    ASSERT_TRUE(this->dut.intr);
130
    ASSERT_EQ(this->dut.irq, 8 + 3);
131
}
132
 
133
TEST_F(PICTestBench, IRQPriority)
134
{
135
    write_reg(0, 0x13);
136
    write_reg(1, 0x08);
137
    write_reg(1, 0x01);
138
 
139
    set_mask(0x00);
140
 
141
    this->cycle(2);
142
    this->dut.intr_in = (1 << 3);
143
    this->cycle(2);
144
    this->dut.intr_in = (1 << 0);
145
    this->cycle(2);
146
    // Two unacknowledged interrupts
147
 
148
    ASSERT_TRUE(this->dut.intr);
149
    ASSERT_EQ(this->dut.irq, 8 + 0);
150
}
151
 
152
TEST_F(PICTestBench, ReadIRR)
153
{
154
    write_reg(0, 0x13);
155
    write_reg(1, 0x08);
156
    write_reg(1, 0x01);
157
 
158
    set_mask(0x00);
159
 
160
    this->cycle(2);
161
    this->dut.intr_in = (1 << 3);
162
    this->cycle(2);
163
    this->dut.intr_in = (1 << 0);
164
    this->cycle(2);
165
    // Two unacknowledged interrupts
166
 
167
    ASSERT_EQ(read_irr(), (1 << 3) | (1 << 0));
168
    ASSERT_EQ(read_isr(), 0);
169
}
170
 
171
TEST_F(PICTestBench, MaskedIntIgnored)
172
{
173
    write_reg(0, 0x13);
174
    write_reg(1, 0x08);
175
    write_reg(1, 0x01);
176
    set_mask(0xff);
177
 
178
    this->cycle(2);
179
    this->dut.intr_in = (1 << 3);
180
    this->cycle(2);
181
 
182
    ASSERT_FALSE(this->dut.intr);
183
}
184
 
185
TEST_F(PICTestBench, NoEOISuppressesSecondIRQ)
186
{
187
    write_reg(0, 0x13);
188
    write_reg(1, 0x08);
189
    write_reg(1, 0x01);
190
    set_mask(0x00);
191
 
192
    this->cycle(2);
193
    this->dut.intr_in = (1 << 3);
194
    this->cycle(1);
195
 
196
    setup_watch_and_ack();
197
    while (!irqs_taken.size())
198
        cycle();
199
 
200
    ASSERT_FALSE(this->dut.intr);
201
    ASSERT_EQ(irqs_taken[0], 8 + 3);
202
}
203
 
204
TEST_F(PICTestBench, NoEOIInhibitsLowerPriority)
205
{
206
    write_reg(0, 0x13);
207
    write_reg(1, 0x08);
208
    write_reg(1, 0x01);
209
    set_mask(0x00);
210
 
211
    this->cycle(2);
212
    this->dut.intr_in = (1 << 3);
213
    this->cycle(1);
214
 
215
    setup_watch_and_ack();
216
    while (!irqs_taken.size())
217
        cycle();
218
 
219
    this->dut.intr_in |= (1 << 7);
220
    cycle(32);
221
 
222
    ASSERT_FALSE(this->dut.intr);
223
    ASSERT_EQ(irqs_taken.size(), 1LU);
224
    ASSERT_EQ(irqs_taken[0], 8 + 3);
225
}
226
 
227
TEST_F(PICTestBench, NoEOIHigherPriorityTaken)
228
{
229
    write_reg(0, 0x13);
230
    write_reg(1, 0x08);
231
    write_reg(1, 0x01);
232
    set_mask(0x00);
233
 
234
    this->cycle(2);
235
    this->dut.intr_in = (1 << 3);
236
    this->cycle(1);
237
 
238
    setup_watch_and_ack();
239
    while (!irqs_taken.size())
240
        cycle();
241
 
242
    after_n_cycles(0, [this] { this->dut.intr_in |= (1 << 0); });
243
    cycle(32);
244
 
245
    ASSERT_FALSE(this->dut.intr);
246
    ASSERT_EQ(irqs_taken.size(), 2LU);
247
    ASSERT_EQ(irqs_taken[0], 8 + 3);
248
    ASSERT_EQ(irqs_taken[1], 8 + 0);
249
    ASSERT_EQ(this->dut.intr_in, 0);
250
}
251
 
252
TEST_F(PICTestBench, EOIReRaises)
253
{
254
    write_reg(0, 0x13);
255
    write_reg(1, 0x08);
256
    write_reg(1, 0x01);
257
    set_mask(0x00);
258
 
259
    this->cycle(2);
260
    this->dut.intr_in = (1 << 3);
261
    this->cycle(1);
262
 
263
    setup_watch_and_ack();
264
    while (!irqs_taken.size())
265
        cycle();
266
 
267
    write_reg(0, 0x20); // Non-specific EOI
268
    cycle(2);
269
 
270
    this->dut.intr_in |= (1 << 3);
271
    cycle(32);
272
 
273
    ASSERT_FALSE(this->dut.intr);
274
    ASSERT_EQ(irqs_taken.size(), 2LU);
275
    ASSERT_EQ(irqs_taken[0], 8 + 3);
276
    ASSERT_EQ(irqs_taken[1], 8 + 3);
277
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.