@@ -4,7 +4,10 @@ import chiseltest._
4
4
import chiseltest .experimental ._
5
5
import org .scalatest ._
6
6
7
+ import com .carlosedp .scalautils .riscvassembler ._
8
+
7
9
import java .io .{File , PrintWriter }
10
+ import java .nio .file .{Files , Paths , DirectoryNotEmptyException }
8
11
9
12
import flatspec ._
10
13
import matchers ._
@@ -29,49 +32,64 @@ class CPUSingleCycleIOWrapper(
29
32
val timerCounter = expose(core.timer0.counter)
30
33
}
31
34
32
- class CPUSingleCycleIOSpec extends AnyFlatSpec with ChiselScalatestTester with should.Matchers {
35
+ class CPUSingleCycleIOSpec
36
+ extends AnyFlatSpec
37
+ with ChiselScalatestTester
38
+ with BeforeAndAfterEach
39
+ with BeforeAndAfter
40
+ with should.Matchers {
33
41
behavior of " GPIO"
34
42
35
43
val cpuFrequency = 25000000
36
44
val bitWidth = 32
37
45
val instructionMemorySize = 1 * 1024
38
46
val memorySize = 1 * 1024
39
47
val ms = cpuFrequency / 1000
48
+ var memoryfile = " "
49
+ val tmpdir = " tmphex"
50
+
51
+ before {
52
+ Files .createDirectories(Paths .get(tmpdir));
53
+ }
54
+ after {
55
+ try {
56
+ Files .deleteIfExists(Paths .get(tmpdir));
57
+ } catch {
58
+ case _ : DirectoryNotEmptyException =>
59
+ // println("Directory not empty")
60
+ }
61
+ }
62
+ override def beforeEach (): Unit =
63
+ memoryfile =
64
+ Paths .get(tmpdir, scala.util.Random .alphanumeric.filter(_.isLetter).take(15 ).mkString + " .hex" ).toString()
65
+ override def afterEach (): Unit = {
66
+ val _ = new File (memoryfile).delete()
67
+ }
40
68
41
- def defaultDut (memoryfile : String ) =
69
+ def defaultDut (prog : String ) = {
70
+ val hex = RISCVAssembler .fromString(prog)
71
+ new PrintWriter (new File (memoryfile)) { write(hex); close }
42
72
test(new CPUSingleCycleIOWrapper (cpuFrequency, bitWidth, instructionMemorySize, memorySize, memoryfile))
43
73
.withAnnotations(
44
74
Seq (
45
75
WriteVcdAnnotation ,
46
76
VerilatorBackendAnnotation ,
47
77
)
48
78
)
79
+ }
49
80
50
81
it should " write to GPIO0" in {
51
- val filename = " CPUSpecMemoryTestFileGPIO0.hex"
52
- /*
53
- lui x1, %hi(0x30001000)
54
- addi x5, x0, -1
55
- addi x3, x3, 1
56
- addi x4, x0, 7
57
- sw x5, 0(x1)
58
- loop: add x2, x2, x3
59
- sw x2, 4(x1)
60
- jal x0, loop
61
- */
62
- new PrintWriter (new File (filename)) {
63
- write("""
64
- 300010b7
65
- fff00293
66
- 00118193
67
- 00700213
68
- 0050a023
69
- 00310133
70
- 0020a223
71
- ff9ff06f
72
- """ .stripMargin); close
73
- }
74
- defaultDut(filename) { c =>
82
+ val prog = """
83
+ lui x1, 0x30001000
84
+ addi x5, x0, -1
85
+ addi x3, x3, 1
86
+ addi x4, x0, 7
87
+ sw x5, 0(x1)
88
+ add x2, x2, x3
89
+ sw x2, 4(x1)
90
+ jal x0, -8
91
+ """
92
+ defaultDut(prog) { c =>
75
93
c.clock.setTimeout(0 )
76
94
c.registers(1 ).peek().litValue should be(0 )
77
95
c.registers(2 ).peek().litValue should be(0 )
@@ -104,29 +122,18 @@ class CPUSingleCycleIOSpec extends AnyFlatSpec with ChiselScalatestTester with s
104
122
c.clock.step(1 ) // sw
105
123
c.GPIO0_value .peek().litValue should be(2 )
106
124
}
107
- new File (filename).delete()
108
125
}
109
126
110
127
behavior of " Timer"
111
128
it should " read timer and wait for 2 ms" in {
112
- val filename = " CPUSpecMemoryTestFileTimer0_1.hex"
113
- /*
114
- main: lui x1, %hi(0x30003000)
129
+ val prog = """
130
+ main: lui x1, 0x30003000
115
131
addi x2, x0, 2
116
132
wait: lw x3, 0(x1)
117
- bne x2, x3, wait
133
+ bne x2, x3, -4
118
134
cont: addi x4, x0, 1
119
- */
120
- new PrintWriter (new File (filename)) {
121
- write("""
122
- 300030b7
123
- 00200113
124
- 0000a183
125
- fe311ee3
126
- 00100213
127
- """ .stripMargin); close
128
- }
129
- defaultDut(filename) { c =>
135
+ """
136
+ defaultDut(prog) { c =>
130
137
c.clock.setTimeout(0 )
131
138
c.registers(1 ).peek().litValue should be(0 )
132
139
c.registers(2 ).peek().litValue should be(0 )
@@ -148,34 +155,20 @@ class CPUSingleCycleIOSpec extends AnyFlatSpec with ChiselScalatestTester with s
148
155
c.clock.step(1 ) // addi
149
156
c.registers(4 ).peek().litValue should be(1 )
150
157
}
151
- new File (filename).delete()
152
158
}
153
159
154
160
it should " reset timer after 1ms and wait for 1 ms" in {
155
- val filename = " CPUSpecMemoryTestFileTimer0_2.hex"
156
- /*
157
- main: lui x1, %hi(0x30003000)
161
+ val prog = """
162
+ main: lui x1, 0x30003000
158
163
addi x2, x0, 1
159
164
wait: lw x3, 0(x1)
160
- bne x2, x3, wait
165
+ bne x2, x3, -4
161
166
cont: sw x0, 0(x1)
162
167
wait2: lw x3, 0(x1)
163
- bne x2, x3, wait2
168
+ bne x2, x3, -4
164
169
cont2: addi x3, x0, 2
165
- */
166
- new PrintWriter (new File (filename)) {
167
- write("""
168
- 300030b7
169
- 00100113
170
- 0000a183
171
- fe311ee3
172
- 0000a023
173
- 0000a183
174
- fe311ee3
175
- 00200193
176
- """ .stripMargin); close
177
- }
178
- defaultDut(filename) { c =>
170
+ """
171
+ defaultDut(prog) { c =>
179
172
c.clock.setTimeout(0 )
180
173
c.registers(1 ).peek().litValue should be(0 )
181
174
c.registers(2 ).peek().litValue should be(0 )
@@ -207,6 +200,5 @@ class CPUSingleCycleIOSpec extends AnyFlatSpec with ChiselScalatestTester with s
207
200
c.clock.step(1 ) // addi
208
201
c.registers(3 ).peek().litValue should be(2 )
209
202
}
210
- new File (filename).delete()
211
203
}
212
204
}
0 commit comments