OSDN Git Service

* public snapshot of sid simulator
[pf3gnuchains/pf3gnuchains3x.git] / sid / component / testsuite / sidcomp.interrupt / arm-interrupt.exp
1 # Testsuite for the ARM reference interrupt controller.
2 # This testsuite tries to exercise just about every aspect of this
3 # component simulation.
4 #
5 # Copyright (C) 1999 Red Hat
6
7 if {! $sidtarget(arm)} then { untested "hw-interrupt-arm/ref not available"; return }
8
9 # The number of available regular interrupt lines.
10 set numLines 32
11
12 # A convenience variable.
13 set all_ones 0xFFFFFFFF
14
15 set test "sid configuration"
16 sid_config_component_test "arm-intr.conf" \
17     "load [sid_find_file libinterrupt.la] interrupt_component_library" \
18     "hw-interrupt-arm/ref"
19 pass $test
20
21
22 set test "sid start"
23 if {[sid_start "arm-intr.conf"]} {
24     pass $test
25 } else {
26     fail $test
27     return
28 }
29
30
31 # A pin we use again, and again, and again.
32 set probe_pin [sid_cmd "sid::pin::new"]
33
34
35 # Set up an array of triggerpoint sensor pins (connected to the victim).
36 # Maintain another array that counts the number of times the triggerpoints are hit.
37
38 catch {unset watchpins triggercount}
39 foreach watchable \
40   {interrupt fast-interrupt irq-raw-status irq-enable-register fiq-raw-status fiq-enable-register} {
41     set test "establish a triggerpoint for watchable state variable: $watchable"
42     set watchpins($watchable) [sid_cmd "sid::pin::new"]
43     sid_cmd "set triggercount($watchable) 0"
44     sid_cmd \
45         "set hook_driven_h4($watchpins($watchable)) {global triggercount driven_h4_value; incr triggercount($watchable) }"
46
47     # Some limited URL encoding hacks.
48     # see sid/include/sidwatchutil.h for the rules.
49     regsub -all -- "-" $watchable "%2D" watchEnc
50     set result [sid_cmd "sid::component::connect_pin $victim watch:${watchEnc}:change $watchpins($watchable)"]
51     set w [sid_cmd "sid::component::attribute_names_in_category $victim watchable"]
52     if {$result == "ok"} { pass $test } else { fail "$test -- $result" }
53 }
54
55
56 # There are no attributes for this component, but let's do this for good measure.
57 set test "attribute list"
58 sid_assert_success "sid::component::attribute_names $victim"
59
60
61 # Check for presence of output pins.
62 set test "get fast-irq pin"
63 sid_assert_success "sid::component::find_pin $victim fast-interrupt"
64 set test "get irq pin"
65 sid_assert_success "sid::component::find_pin $victim interrupt"
66
67
68 # Check for presence of input pins. Record the names given to them by
69 # the Tcl bridge--we use them later.
70 set test "get reset pin"
71 if {[set reset_pin [sid_cmd "sid::component::find_pin $victim reset"]] != ""} {
72     pass $test
73 } else {
74     fail $test
75 }
76
77 set test "get fast interrupt source pin"
78 if {[set firq_source [sid_cmd "sid::component::find_pin $victim fast-interrupt-source"]] != ""} {
79     pass $test
80 } else {
81     fail $test
82 }
83
84 # Check for all 32 interrupt input lines.
85 for {set i 0} {$i < $numLines} {incr i} {
86     set test "get interrupt-source-$i pin"
87     if {[set irq_source($i) [sid_cmd "sid::component::find_pin $victim interrupt-source-$i"]] != ""} {
88         pass $test
89     } else {
90         fail $test
91     }
92 }
93
94
95 # Check for the presence of the register set (a named bus). Record the
96 # name given to it by sid_cmd, as we'll use it throughout this
97 # testsuite. 
98 set test "get irq-register bus" 
99 if {[set irqbus [sid_cmd "sid::component::find_bus $victim irq-registers"]] != ""} {
100     pass $test
101 } else {
102     fail $test
103 }
104
105 set test "get fiq-register bus" 
106 if {[set fiqbus [sid_cmd "sid::component::find_bus $victim fiq-registers"]] != ""} {
107     pass $test
108 } else {
109     fail $test
110 }
111
112
113    
114 # Write to reserved fields.  Just make sure these do nothing.
115 foreach location {0x0 0x1} {
116   set test "writing to reserved irq-register (offset $location)"
117   sid_assert_success "sid::bus::write_h4_l4 $irqbus $location $all_ones"
118 }
119 foreach location {0x0 0x4} {
120   set test "writing to reserved fiq-register (offset $location)"
121   sid_assert_success "sid::bus::write_h4_l4 $fiqbus $location $all_ones"
122 }
123
124 # Read from reserved fields.  Again, ensure nothing bad happens.
125 foreach location {0xC 0x10} {
126   set test "reading from reserved irq-register (offset $location)"
127   sid_assert_success "sid::bus::read_h4_l4 $irqbus $location"
128 }
129 foreach location {0x10C} {
130   set test "reading from reserved fiq-register (offset $location)"
131   sid_assert_success "sid::bus::read_h4_l4 $fiqbus $location"
132 }
133
134 set test "Save state"
135 set state [sid_cmd "sid::component::attribute_value $victim state-snapshot"]
136 if {$state != ""} then { pass $test } else { fail $test }
137
138 # Allow interrupts from any source.
139 # This is a basic version of the more complete testing that happens
140 # further on in this script.
141
142 foreach pattern {0x0 0x12345678 0x55555555 0xAAAAAAAA 0xFFFFFFFF} {
143     set test "disable all interrupt lines"
144     sid_assert_success "sid::bus::write_h4_l4 $irqbus 0x0C $all_ones"
145
146     set test "validate all interrupt lines are disabled"
147     set result [sid_cmd "sid::bus::read_h4_l4 $irqbus 0x8"]
148
149     set status [lindex $result 0]
150     if {[lindex $result 0] == "ok"} {
151         if {[lindex $result 1] == 0} { pass $test } else { fail $test }
152     } else {
153         fail "$test (bus error)"
154     }
155
156     set test "initialise set of enabled interrupt lines"
157     sid_assert_success "sid::bus::write_h4_l4 $irqbus 0x8 $pattern"
158
159     set test "validate set of enabled interrupt lines"
160     set result [sid_cmd "sid::bus::read_h4_l4 $irqbus 0x8"]
161     set status [lindex $result 0]
162     if {[lindex $result 0] == "ok"} {
163         if {[lindex $result 1] == $pattern} { pass $test } else { fail $test }
164     } else {
165         fail "$test (bus error)"
166     }
167 }
168
169 set test "Repeat Save state"
170 set rpstate [sid_cmd "sid::component::attribute_value $victim state-snapshot"]
171 set comp_res [string compare $state $rpstate]
172 if {$comp_res != 0} then { pass $test } else { fail $test }
173
174 set test "Restore State"
175 set ok [sid_cmd "sid::component::set_attribute_value $victim state-snapshot [list $state]"]
176 if {$ok == "ok"} then { pass $test } else { fail $test }
177
178 # At the completion of this test, all interrupts *should* be enabled.
179
180
181 # Generate an interrupt on each of the regular interrupt lines.
182 # Once it is acknowledged, suspend the interrupt source.
183
184 # This is a double nested loop -- 32*32 tests are performed to make
185 # sure that other interrupt lines going high does not invoke an
186 # interrupt (ie. to ensure that the masking works correctly for all
187 # cases).
188
189 sid_cmd "set hook_driven_h4($probe_pin) { 
190     global driven_h4_value interrupted
191     # Make the pin values sensible.
192     # The pin values are normally negated in the controller to make it
193     # easy to connect this component to related CPUs like the ARM7.
194     if \[expr \$driven_h4_value == 0\] { 
195         set interrupted 1 
196     } else {
197         set interrupted 0
198     }
199 }"
200
201 sid_cmd "sid::component::connect_pin $victim interrupt $probe_pin"
202
203 set failures 0
204 for {set i 0} {$i < $numLines} {incr i} {
205     set test "disable all interrupt lines"
206     sid_assert_success "sid::bus::write_h4_l4 $irqbus 0x0C $all_ones"
207
208     set test "validate all interrupt lines are disabled"
209     set result [sid_cmd "sid::bus::read_h4_l4 $irqbus 0x8"]
210     if {[lindex $result 0] == "ok"} {
211         set val [lindex $result 1]
212         if {$val != 0} {
213             incr failures
214             fail $test
215         }
216     } else {
217         incr failures
218         fail "$test -- [lindex $result 0]"
219     }
220
221     set test "enable interrupt line $i"
222     sid_assert_success "sid::bus::write_h4_l4 $irqbus 0x8 [expr 1 << $i]"
223
224     set test "validate only interrupt line $i is enabled"
225     set result [sid_cmd "sid::bus::read_h4_l4 $irqbus 0x8"]
226     if {[lindex $result 0] == "ok"} {
227         if {[lindex $result 1] != [expr 1 << $i]} {
228             incr failures
229             fail $test
230         }
231     } else {
232         incr failures
233         fail "$test -- [lindex $result 0]"
234     }
235     
236     for {set j 0} {$j < $numLines} {incr j} {
237         sid_cmd "set interrupted 0"
238         
239         # Raise an interrupt on interrupt line `j'.
240         sid_cmd "sid::pin::driven_h4 $irq_source($j) 1"
241         
242         if {$i == $j} { set test "permitting" } else { set test "masking" }
243         append test " interrupt from interrupt $j when enabling interrupt $i only"
244             
245         set result [sid_cmd "set interrupted"]
246         if {$result == "1"} {
247             if {$i == $j} { 
248                 set test_save $test
249                 set test "bit $i is set in the masked status register"
250                 set result [sid_cmd "sid::bus::read_h4_l4 $irqbus 0"]
251                 if {[lindex $result 0] == "ok"} {
252                     if {[lindex $result 1] != [expr 1 << $i]} {
253                         incr failures
254                         fail $test
255                         continue
256                     }
257                 } else {
258                     incr failures
259                     fail "$test -- [lindex $result 0]"
260                     continue
261                 }
262                 set test $test_save
263             } else {
264                 incr failures
265                 fail $test
266                 continue
267             }
268         } else {
269             if {$i == $j} { 
270                 incr failures
271                 fail $test
272                 continue
273             }
274         }
275         # Lower the interrupt source.   
276         sid_cmd "sid::pin::driven_h4 $irq_source($j) 0"
277     }
278 }
279 if {!$failures} { pass "interrupt masking" }
280 sid_cmd "sid::component::disconnect_pin $victim interrupt $probe_pin"
281
282 # Disable the fast interrupt.
283 set test "disable fast interrupt"
284 sid_assert_success "sid::bus::write_h4_l4 $fiqbus 0xC $all_ones"
285
286 set test "validate fast interrupt disabled"
287 set result [sid_cmd "sid::bus::read_h4_l4 $fiqbus 0x8"]
288 set status [lindex $result 0]
289 if {$status == "ok"} {
290     if {[lindex $result 1] == "0"} { pass $test } else { fail $test }
291 } else {
292     fail "$test (bus error; status $status)"
293 }
294
295 # Enable the fast interrupt.
296 set test "enable fast interrupt"
297 sid_assert_success "sid::bus::write_h4_l4 $fiqbus 0x8 1"
298
299 set test "validate fast interrupt is enabled"
300 set result [sid_cmd "sid::bus::read_h4_l4 $fiqbus 0x8"]
301 set status [lindex $result 0]
302 if {$status == "ok"} {
303     pass $test
304 } else {
305     fail "$test (bus error; status $status)"
306 }
307
308 # Generate a fast interrupt.
309 set test "fast interrupt"
310
311 sid_cmd "set interrupted 0"
312 sid_cmd "sid::component::connect_pin $victim fast-interrupt $probe_pin"
313 sid_cmd "sid::pin::driven_h4 $firq_source 1"
314 if {[sid_cmd "set interrupted"] == 1} {
315     pass $test
316 } else {
317     fail $test
318 }
319
320 # Clear the interrupt.
321 sid_cmd "sid::pin::driven_h4 $firq_source 0"
322 sid_cmd "sid::component::disconnect_pin $victim fast-interrupt $probe_pin"
323
324
325 # Test the programmed interrupt.  After writing to the appropriate
326 # register in the interrupt controller, there should be a pending
327 # interrupt from interrupt no. 1.
328
329 sid_cmd "set interrupted 0"
330
331 set test "disable all interrupt lines"
332 sid_assert_success "sid::bus::write_h4_l4 $irqbus 0x0C $all_ones"
333
334 set test "enable interrupt line 1 only"
335 sid_assert_success "sid::bus::write_h4_l4 $irqbus 0x8 2"
336 sid_cmd "sid::pin::driven_h4 $irq_source(1) 0"
337
338 sid_cmd "sid::component::connect_pin $victim interrupt $probe_pin"
339 set result [sid_cmd "set interrupted"]
340
341 # Invoke the programmed interrupt by writing to the software IRQ register.
342 set test "programmed interrupt"
343 sid_cmd "sid::bus::write_h4_l4 $irqbus 0x10 2"
344 if {[sid_cmd "set interrupted"] == 1} { pass $test } else { fail $test }
345
346
347 # Test if triggerpoints fired correctly.
348
349 set test "interrupt triggerpoint fired 69 times"
350 set count [sid_cmd "set triggercount(interrupt)"]
351 if {$count == "69"} { pass $test } else { fail "$test; fired $count times" }
352
353 set test "fast-interrupt triggerpoint fired 3 times"
354 set count [sid_cmd "set triggercount(fast-interrupt)"]
355 if {$count == "3"} { pass $test } else { fail "$test; fired $count times" }
356
357 set test "irq-raw-status triggerpoint fired 2049 times"
358 set count [sid_cmd "set triggercount(irq-raw-status)"]
359 if {$count == "2049"} { pass $test } else { fail "$test; fired $count times" }
360
361 set test "irq-enable-register triggerpoint fired 73 times"
362 set count [sid_cmd "set triggercount(irq-enable-register)"]
363 if {$count == "73"} { pass $test } else { fail "$test; fired count times" }
364
365 set test "fiq-raw-status triggerpoint fired twice"
366 set count [sid_cmd "set triggercount(fiq-raw-status)"]
367 if {$count == "2"} { pass $test } else { fail "$test; fired $count times" }
368
369 set test "fiq-enable-register triggerpoint fired once"
370 set count [sid_cmd "set triggercount(fiq-enable-register)"]
371 if {$count == "1"} { pass $test } else { fail "$test; fired $count times" }
372
373 catch {unset watchpins triggercount}
374
375
376 set test "sid stop"
377 if {[sid_stop]} { pass $test } else { fail $test ; return }
378
379 # zap temp file if tests were successful
380 global exit_status
381 if {$exit_status == "0"} {
382     file delete "arm-intr.conf"
383 }