@@ -8,312 +8,18 @@ import org.scalatest.matchers.must.Matchers
88class MainSpec extends AnyFreeSpec with Matchers with ChiselSim {
99 " Main should execute LUI correctly" in {
1010 simulate(new Main ()) { dut =>
11- // LUI x1, 0x12345
12- val instr = " b00010010001101000101_00001_0110111" .U (32 .W ) // opcode=0110111
13- dut.io.instruction.poke(instr)
14- dut.clock.step(1 )
15-
16- // Expect register x1 to hold immediate shifted left 12 bits
17- dut.io.read_addr_C.poke(1 .U )
18- dut.io.out_C.expect(" h12345000" .U )
19- }
20- }
21-
22- " Main should execute AUIPC correctly" in {
23- simulate(new Main ()) { dut =>
24- // AUIPC x2, 0x1
25- val instr = " b00000000000000000001_00010_0010111" .U (32 .W ) // opcode=0010111
26- dut.io.instruction.poke(instr)
27- dut.clock.step(1 )
28-
29- // PC is 0 in this design, so x2 = pc + imm << 12
30- dut.io.read_addr_C.poke(2 .U )
31- dut.io.out_C.expect(" b00000000000000000001000000000000" .U )
32- }
33- }
34-
35- " Main should execute ADDI correctly" in {
36- simulate(new Main ()) { dut =>
37- // First, write x1 = 5
38- dut.io.write_enable.poke(true .B )
39- dut.io.write_addr.poke(1 .U )
40- dut.io.in.poke(5 .U )
41- dut.clock.step(1 )
42-
43- // ADDI x2, x1, 7
44- val instr = " b000000000111_00001_000_00010_0010011" .U (32 .W )
45- dut.io.instruction.poke(instr)
46- dut.clock.step(1 )
47-
48- // x2 should be 5 + 7 = 12
49- dut.io.read_addr_C.poke(2 .U )
50- dut.io.out_C.expect(12 .U )
51- }
52- }
53-
54- " Main should execute SLTI correctly" in {
55- simulate(new Main ()) { dut =>
56- // x1 = 5
57- dut.io.write_enable.poke(true .B )
58- dut.io.write_addr.poke(1 .U )
59- dut.io.in.poke(5 .U )
60- dut.clock.step(1 )
61- dut.io.write_enable.poke(false .B )
11+ dut.io.debug_write.poke(true .B );
12+ dut.io.debug_write_data.poke(" b00010010001101000101_00001_0110111" .U (32 .W ));
13+ dut.io.debug_write_address.poke(0 .U );
6214
63- // SLTI x2, x1, 7 -> 5 < 7 ? 1 : 0
64- val instr = " b00000000111_00001_010_00010_0010011" .U (32 .W )
65- dut.io.instruction.poke(instr)
66- dut.clock.step(1 )
67-
68- // x2 should be 1
69- dut.io.read_addr_C.poke(2 .U )
70- dut.io.out_C.expect(1 .U )
71- }
72- }
73-
74- " Main should execute SLTIU correctly" in {
75- simulate(new Main ()) { dut =>
76- // x1 = 5
77- dut.io.write_enable.poke(true .B )
78- dut.io.write_addr.poke(1 .U )
79- dut.io.in.poke(5 .U )
8015 dut.clock.step(1 )
81- dut.io.write_enable.poke(false .B )
8216
83- // SLTIU x2, x1, 7 -> 5 < 7 ? 1 : 0 (unsigned)
84- val instr = " b00000000111_00001_011_00010_0010011" .U (32 .W )
85- dut.io.instruction.poke(instr)
86- dut.clock.step(1 )
17+ dut.io.debug_write.poke(false .B );
18+ dut.io.execute.poke(true .B );
8719
88- // x2 should be 1
89- dut.io.read_addr_C.poke(2 .U )
90- dut.io.out_C.expect(1 .U )
91- }
92- }
93-
94- " Main should execute XORI correctly" in {
95- simulate(new Main ()) { dut =>
96- // x1 = 0b1010
97- dut.io.write_enable.poke(true .B )
98- dut.io.write_addr.poke(1 .U )
99- dut.io.in.poke(" b1010" .U )
10020 dut.clock.step(1 )
101- dut.io.write_enable.poke(false .B )
102-
103- // XORI x2, x1, 0b1100 -> 0b1010 ^ 0b1100 = 0b0110
104- val instr = " b000000001100_00001_100_00010_00100_11" .U (32 .W )
105- dut.io.instruction.poke(instr)
21+
10622 dut.clock.step(1 )
107-
108- dut.io.read_addr_C.poke(2 .U )
109- dut.io.out_C.expect(" b0110" .U )
110- }
111- }
112-
113- " Main should execute ORI correctly" in {
114- simulate(new Main ()) { dut =>
115- // x1 = 0b1010
116- dut.io.write_enable.poke(true .B )
117- dut.io.write_addr.poke(1 .U )
118- dut.io.in.poke(" b1010" .U )
119- dut.clock.step(1 )
120- dut.io.write_enable.poke(false .B )
121-
122- // ORI x2, x1, 0b1100 -> 0b1010 | 0b1100 = 0b1110
123- val instr = " b00000001100_00001_110_00010_00100_11" .U (32 .W )
124- dut.io.instruction.poke(instr)
125- dut.clock.step(1 )
126-
127- dut.io.read_addr_C.poke(2 .U )
128- dut.io.out_C.expect(" b1110" .U )
129- }
130- }
131-
132- " Main should execute ANDI correctly" in {
133- simulate(new Main ()) { dut =>
134- // x1 = 0b1010
135- dut.io.write_enable.poke(true .B )
136- dut.io.write_addr.poke(1 .U )
137- dut.io.in.poke(" b1010" .U )
138- dut.clock.step(1 )
139- dut.io.write_enable.poke(false .B )
140-
141- // ANDI x2, x1, 0b1100 -> 0b1010 & 0b1100 = 0b1000
142- val instr = " b00000001100_00001_111_00010_00100_11" .U (32 .W )
143- dut.io.instruction.poke(instr)
144- dut.clock.step(1 )
145-
146- dut.io.read_addr_C.poke(2 .U )
147- dut.io.out_C.expect(" b1000" .U )
148- }
149- }
150-
151- " Main should execute SLLI correctly" in {
152- simulate(new Main ()) { dut =>
153- // x1 = 0b0001
154- dut.io.write_enable.poke(true .B )
155- dut.io.write_addr.poke(1 .U )
156- dut.io.in.poke(" b0001" .U )
157- dut.clock.step(1 )
158- dut.io.write_enable.poke(false .B )
159-
160- // SLLI x2, x1, 2 -> 0b0001 << 2 = 0b0100
161- val instr = " b00000_0_00010_00001_001_00010_00100_11" .U (32 .W )
162- dut.io.instruction.poke(instr)
163- dut.clock.step(1 )
164-
165- dut.io.read_addr_C.poke(2 .U )
166- dut.io.out_C.expect(" b0100" .U )
167- }
168- }
169-
170- " Main should execute SRLI correctly" in {
171- simulate(new Main ()) { dut =>
172- // x1 = 0b0100
173- dut.io.write_enable.poke(true .B )
174- dut.io.write_addr.poke(1 .U )
175- dut.io.in.poke(" b0100" .U )
176- dut.clock.step(1 )
177- dut.io.write_enable.poke(false .B )
178-
179- // SRLI x2, x1, 2 -> 0b0100 >> 2 = 0b0001
180- val instr = " b00000000010_00001_101_00010_0010011" .U (32 .W )
181- dut.io.instruction.poke(instr)
182- dut.clock.step(1 )
183-
184- dut.io.read_addr_C.poke(2 .U )
185- dut.io.out_C.expect(" b0001" .U )
186- }
187- }
188-
189- " Main should execute SRAI correctly" in {
190- simulate(new Main ()) { dut =>
191- // x1 = -8
192- dut.io.write_enable.poke(true .B )
193- dut.io.write_addr.poke(1 .U )
194- dut.io.in.poke(" b11111111111111111111111111111000" .U )
195- dut.clock.step(1 )
196- dut.io.write_enable.poke(false .B )
197-
198- // SRAI x2, x1, 2 -> -8 >> 2 = -2
199- val instr = " b01000_0_00010_00001_101_00010_00100_11" .U (32 .W )
200- dut.io.instruction.poke(instr)
201- dut.clock.step(1 )
202-
203- dut.io.read_addr_C.poke(2 .U )
204- dut.io.out_C.expect(" b11111111111111111111111111111110" .U )
205- }
206- }
207-
208- " Main should execute ADD correctly" in {
209- simulate(new Main ()) { dut =>
210- // x1 = 5, x2 = 7
211- dut.io.write_enable.poke(true .B )
212- dut.io.write_addr.poke(1 .U )
213- dut.io.in.poke(5 .U )
214- dut.clock.step(1 )
215- dut.io.write_addr.poke(2 .U )
216- dut.io.in.poke(7 .U )
217- dut.clock.step(1 )
218- dut.io.write_enable.poke(false .B )
219-
220- // ADD x3, x1, x2 -> 5 + 7 = 12
221- val instr = " b0000000_00010_00001_000_00011_0110011" .U (32 .W )
222- dut.io.instruction.poke(instr)
223- dut.clock.step(1 )
224-
225- dut.io.read_addr_C.poke(3 .U )
226- dut.io.out_C.expect(12 .U )
227- }
228- }
229-
230- " Main should execute SUB correctly" in {
231- simulate(new Main ()) { dut =>
232- // x1 = 10, x2 = 3
233- dut.io.write_enable.poke(true .B )
234- dut.io.write_addr.poke(1 .U )
235- dut.io.in.poke(10 .U )
236- dut.clock.step(1 )
237- dut.io.write_addr.poke(2 .U )
238- dut.io.in.poke(3 .U )
239- dut.clock.step(1 )
240- dut.io.write_enable.poke(false .B )
241-
242- // SUB x3, x1, x2 -> 10 - 3 = 7
243- val instr = " b0100000_00010_00001_000_00011_01100_11" .U (32 .W )
244- dut.io.instruction.poke(instr)
245- dut.clock.step(1 )
246-
247- dut.io.read_addr_C.poke(3 .U )
248- dut.io.out_C.expect(7 .U )
249- }
250- }
251-
252- " Main should execute SLL correctly" in {
253- simulate(new Main ()) { dut =>
254- // x1 = 3, x2 = 2
255- dut.io.write_enable.poke(true .B )
256- dut.io.write_addr.poke(1 .U )
257- dut.io.in.poke(3 .U )
258- dut.clock.step(1 )
259- dut.io.write_addr.poke(2 .U )
260- dut.io.in.poke(2 .U )
261- dut.clock.step(1 )
262- dut.io.write_enable.poke(false .B )
263-
264- // SLL x3, x1, x2 -> 3 << (2 & 0x1F) = 12
265- val instr = " b0000000_00010_00001_001_00011_01100_11" .U (32 .W )
266- dut.io.instruction.poke(instr)
267- dut.clock.step(1 )
268-
269- dut.io.read_addr_C.poke(3 .U )
270- dut.io.out_C.expect(12 .U )
271- }
272- }
273-
274- " Main should execute SLT (signed) correctly" in {
275- simulate(new Main ()) { dut =>
276- // x1 = -1 (0xFFFFFFFF), x2 = 1
277- dut.io.write_enable.poke(true .B )
278- dut.io.write_addr.poke(1 .U )
279- dut.io.in.poke(" hFFFFFFFF" .U ) // -1 as 32-bit two's complement
280- dut.clock.step(1 )
281- dut.io.write_addr.poke(2 .U )
282- dut.io.in.poke(1 .U )
283- dut.clock.step(1 )
284- dut.io.write_enable.poke(false .B )
285-
286- // SLT x3, x1, x2 -> (-1 < 1) ? 1 : 0 => 1
287- val instr = " b0000000_00010_00001_010_00011_01100_11" .U (32 .W )
288- dut.io.instruction.poke(instr)
289- dut.clock.step(1 )
290-
291- dut.io.read_addr_C.poke(3 .U )
292- dut.io.out_C.expect(1 .U )
293- }
294- }
295-
296- " Main should execute SLTU (unsigned) correctly" in {
297- simulate(new Main ()) { dut =>
298- // x1 = 0xFFFFFFFF (unsigned 4294967295), x2 = 1
299- // unsigned: 0xFFFFFFFF > 1 -> result should be 0
300- dut.io.write_enable.poke(true .B )
301- dut.io.write_addr.poke(1 .U )
302- dut.io.in.poke(" hFFFFFFFF" .U ) // large unsigned value
303- dut.clock.step(1 )
304- dut.io.write_addr.poke(2 .U )
305- dut.io.in.poke(1 .U )
306- dut.clock.step(1 )
307- dut.io.write_enable.poke(false .B )
308-
309- // SLTU x3, x1, x2 -> (0xFFFFFFFF < 1) ? 1 : 0 => 0 (unsigned comparison)
310- val instr = " b0000000_00010_00001_011_00011_01100_11" .U (32 .W )
311- dut.io.instruction.poke(instr)
312- dut.clock.step(1 )
313-
314- dut.io.read_addr_C.poke(3 .U )
315- dut.io.out_C.expect(0 .U )
31623 }
31724 }
318-
31925}
0 commit comments