Tue, 08 Mar 2011 09:40:42 +0000
Fix project layout to follow standards
1 #! /bin/bash
2 # \
3 export RLWRAP_ #\
4 exec rlwrap -C lm32-ctl -I /opt/quartus/quartus/bin/quartus_stp --64bit -t "$0" "$@"
6 ########################### LOW LEVEL ACCESS #########################
7 proc jtag_put {val} {
8 device_virtual_dr_shift -instance_index 0 -length 11 -dr_value "[format %03X $val]" -value_in_hex -no_captured_dr_value
9 }
11 proc jtag_get {} {
12 return 0x[device_virtual_dr_shift -instance_index 0 -length 11 -dr_value 000 -value_in_hex]
13 }
15 ############################ SAFE-ISHL ACCESS #########################
17 proc jtag_val {idx val} {
18 set v [expr {($val << 3) | $idx}]
19 jtag_put "$v"
20 }
22 proc jtag_cmd {idx cmd} {
23 set val [expr {$cmd << 4}]
24 jtag_val "$idx" "$val"
25 }
27 proc jtag_low {i} {
28 set high 1
29 while {$high >= 1} {
30 set val [jtag_get]
31 set high [expr {($val >> $i) & 1}]
32 }
33 return [expr {$val >> 3}]
34 }
36 proc jtag_high {i} {
37 set high 0
38 while {$high < 1} {
39 set val [jtag_get]
40 set high [expr {($val >> $i) & 1}]
41 }
42 return [expr {$val >> 3}]
43 }
45 ############################## COMMANDS ###############################
47 proc jtag_read_addr {addr} {
48 jtag_cmd 0 1
49 jtag_val 0 "[expr {($addr >> 24) & 0xff}]"
50 jtag_val 0 "[expr {($addr >> 16) & 0xff}]"
51 jtag_val 0 "[expr {($addr >> 8) & 0xff}]"
52 jtag_val 0 "[expr {($addr >> 0) & 0xff}]"
54 return [jtag_low 2]
55 }
57 proc jtag_read_next {} {
58 jtag_cmd 0 3
59 return [jtag_low 2]
60 }
62 proc jtag_read_memory {addr len} {
63 set out [list]
65 if {$len > 0} {
66 lappend out "[format %02X [jtag_read_addr $addr]]"
67 }
69 for {set i 1} {$i < $len} {incr i} {
70 #set x [expr {$addr+$i}]
71 #lappend out "[format %02X [jtag_read_addr $x]]"
72 lappend out "[format %02X [jtag_read_next]]"
73 }
74 return "$out"
75 }
77 proc jtag_write_addr {addr val} {
78 jtag_cmd 0 2
79 jtag_val 0 "[expr {($addr >> 24) & 0xff}]"
80 jtag_val 0 "[expr {($addr >> 16) & 0xff}]"
81 jtag_val 0 "[expr {($addr >> 8) & 0xff}]"
82 jtag_val 0 "[expr {($addr >> 0) & 0xff}]"
83 jtag_val 0 "$val"
85 return [jtag_low 2]
86 }
88 proc jtag_write_next {val} {
89 jtag_cmd 0 4
90 jtag_val 0 "$val"
91 return [jtag_low 2]
92 }
94 proc jtag_write_memory {addr data} {
95 set first 1
96 foreach j $data {
97 if {$first == 1} {
98 set first 0
99 jtag_write_addr "$addr" "$j"
100 } else {
101 jtag_write_next "$j"
102 }
103 }
104 }
106 proc jtag_uart_write {val} {
107 jtag_low 1
108 jtag_val 1 "$val"
109 }
111 proc jtag_uart_read {} {
112 set val [jtag_get]
113 while {($val & 1) == 1} {
114 jtag_val 2 0
115 set val [jtag_get]
116 set inb [expr {$val >> 3}]
117 puts -nonewline "[format %02X $inb] "
118 }
119 puts "."
120 }
122 proc jtag_write_csr {csr val} {
123 jtag_cmd 0 5
124 jtag_val 0 "[expr {($val >> 24) & 0xff}]"
125 jtag_val 0 "[expr {($val >> 16) & 0xff}]"
126 jtag_val 0 "[expr {($val >> 8) & 0xff}]"
127 jtag_val 0 "[expr {($val >> 0) & 0xff}]"
128 jtag_val 0 "$csr"
130 return [jtag_low 2]
131 }
133 proc jtag_break {} {
134 jtag_cmd 0 6
135 }
137 proc jtag_reset {} {
138 jtag_cmd 0 7
139 }
141 # Move back to idle state
142 proc jtag_sync {} {
143 for {set i 0} {$i < 10} {incr i} {
144 jtag_cmd 0 0
145 after 20
146 }
147 }
149 ################################# ASM #################################
151 proc opcode {val} {
152 switch $val {
153 0 { return "srui" }
154 1 { return "nori" }
155 2 { return "muli" }
156 3 { return "sh" }
157 4 { return "lb" }
158 5 { return "sri" }
159 6 { return "xori" }
160 7 { return "lh" }
161 8 { return "andi" }
162 9 { return "xnori" }
163 10 { return "lw" }
164 11 { return "lhu" }
165 12 { return "sb" }
166 13 { return "addi" }
167 14 { return "ori" }
168 15 { return "sli" }
169 16 { return "lbu" }
170 17 { return "be" }
171 18 { return "bg" }
172 19 { return "bge" }
173 20 { return "bgeu" }
174 21 { return "bgu" }
175 22 { return "sw" }
176 23 { return "bne" }
177 24 { return "andhi" }
178 25 { return "cmpei" }
179 26 { return "cmpgi" }
180 27 { return "cmpgei" }
181 28 { return "cmpgeui" }
182 29 { return "cmpgui" }
183 30 { return "orhi" }
184 31 { return "cmpnei" }
185 32 { return "sru" }
186 33 { return "nor" }
187 34 { return "mul" }
188 35 { return "divu" }
189 36 { return "rcsr" }
190 37 { return "sr" }
191 38 { return "xor" }
192 39 { return "div" }
193 40 { return "and" }
194 41 { return "xnor" }
195 42 { return "??" }
196 43 { return "raise" }
197 44 { return "sextb" }
198 45 { return "add" }
199 46 { return "or" }
200 47 { return "sl" }
201 48 { return "b" }
202 49 { return "modu" }
203 50 { return "sub" }
204 51 { return "??" }
205 52 { return "wcsr" }
206 53 { return "mod" }
207 54 { return "call" }
208 55 { return "sexth" }
209 56 { return "bi" }
210 57 { return "cmpe" }
211 58 { return "cmpg" }
212 59 { return "cmpge" }
213 60 { return "cmpgeu" }
214 61 { return "cmpgu" }
215 62 { return "calli" }
216 63 { return "cmpne" }
217 }
218 }
220 proc reg {i} {
221 switch $i {
222 26 { return "gp" }
223 27 { return "fp" }
224 28 { return "sp" }
225 29 { return "ra" }
226 30 { return "ea" }
227 31 { return "ba" }
228 default { return "r$i" }
229 }
230 }
232 proc csr {i} {
233 switch $i {
234 0 { return "IE" }
235 1 { return "IM" }
236 2 { return "IP" }
237 3 { return "ICC" }
238 4 { return "DCC" }
239 5 { return "CC" }
240 6 { return "CFG" }
241 7 { return "EBA" }
242 8 { return "DC" }
243 9 { return "DEBA" }
244 14 { return "JTX" }
245 15 { return "JRX" }
246 16 { return "BP0" }
247 17 { return "BP1" }
248 18 { return "BP2" }
249 19 { return "BP3" }
250 24 { return "WP0" }
251 25 { return "WP1" }
252 26 { return "WP2" }
253 27 { return "WP3" }
254 }
255 }
257 proc imm16 {i} {
258 if {$i >= 32768} {
259 return "-[expr {65536 - $i}]"
260 } else {
261 return "+$i"
262 }
263 }
265 proc imm26 {i} {
266 if {$i >= 33554432} {
267 return "-[expr {67108864 - $i}]"
268 } else {
269 return "+$i"
270 }
271 }
273 proc opfmt {op} {
274 set code [expr {$op >> 26}]
275 set r0 [expr {($op >> 21) & 31}]
276 set r1 [expr {($op >> 16) & 31}]
277 set r2 [expr {($op >> 11) & 31}]
278 set i16 [expr {$op & 0xffff}]
279 set i26 [expr {$op & 0x3ffffff}]
281 if {$code == 4 || $code == 7 || $code == 10 || $code == 11 || $code == 16} {
282 # lb, lh, lw, lhu, lbu
283 return "[opcode $code] [reg $r1], ([reg $r0][imm16 $i16])"
284 } elseif {$code == 3 || $code == 12 || $code == 22} { # sh, sb, sw
285 return "[opcode $code] ([reg $r0][imm16 $i16]), [reg $r1]"
286 } elseif {$code <= 32} { # (op, op, imm) instruction
287 return "[opcode $code] [reg $r1], [reg $r0], [imm16 $i16]"
288 } elseif {$code == 48 || $code == 54} { # b, call
289 return "[opcode $code] [reg $r0]"
290 } elseif {$code == 36} { # rcsr
291 return "[opcode $code] [reg $r2], [csr $r0]"
292 } elseif {$code == 52} { # wcsr
293 return "[opcode $code] [csr $r0], [reg $r1]"
294 } elseif {$code == 56 || $code == 62 || $code == 43} { # bi, calli, raise
295 return "[opcode $code] [imm26 $i26]"
296 } elseif {$code == 44 || $code == 55} { # sextb, sexth
297 return "[opcode $code] [reg $r2], [reg $r0]"
298 } else {
299 return "[opcode $code] [reg $r2], [reg $r1], [reg $r0]"
300 }
301 }
303 ################################ CMDS #################################
305 proc read_memory {addr len} {
306 if {$addr == ""} {set addr 0}
307 if {$len == ""} {set len 64}
309 # Align read to 16-byte boundary
310 set a_addr [expr {$addr & ~0xf}]
311 set a_len [expr {($len + 15) & ~0xf}]
313 set vals [jtag_read_memory $a_addr $a_len]
315 for {set i 0} {$i < $a_len} {set i [expr {$i + 16}]} {
316 puts -nonewline [format %08X: $a_addr]
317 set a_addr [expr {$a_addr + 16}]
318 for {set j 0} {$j < 4} {incr j} {
319 set vals [lassign $vals b0 b1 b2 b3]
320 puts -nonewline " $b0$b1$b2$b3"
321 }
322 puts ""
323 }
325 set nextcmd [list]
326 lappend nextcmd "read"
327 lappend nextcmd $a_addr
328 lappend nextcmd $a_len
329 }
331 proc write_memory {addr val} {
332 set data [list]
333 lappend data [expr {($val >> 24) & 0xff}]
334 lappend data [expr {($val >> 16) & 0xff}]
335 lappend data [expr {($val >> 8) & 0xff}]
336 lappend data [expr {($val >> 0) & 0xff}]
337 jtag_write_memory $addr $data
338 }
340 proc dump_memory {addr len} {
341 if {$addr == ""} {set addr 0}
342 if {$len == ""} {set len 16}
344 # Align read to 4-byte boundary
345 set a_addr [expr {$addr & ~0x3}]
346 set a_len [expr {$len * 4}]
347 set a_end [expr {$a_addr + $a_len}]
349 set vals [jtag_read_memory $a_addr $a_len]
351 for {set a $a_addr} {$a < $a_end} {set a [expr {$a + 4}]} {
352 set vals [lassign $vals b0 b1 b2 b3]
353 puts "[format %08X $a]: [opfmt 0x$b0$b1$b2$b3]"
354 }
356 set nextcmd [list]
357 lappend nextcmd "dump"
358 lappend nextcmd [expr {$a_addr + $a_len}]
359 lappend nextcmd [expr {$a_len / 4}]
360 }
362 proc send {data} {
363 foreach j $data {
364 jtag_uart_write $j
365 }
366 }
368 proc transfer {prompt file offset len target} {
369 set data [open $file]
370 fconfigure $data -translation binary
371 seek $data $offset
373 set progress 0
374 for {set done 0} {$done < $len} {set done [expr {$done+$did}]} {
375 puts -nonewline "\r$prompt$done bytes"
377 set rest [expr {$len - $done}]
378 if {$rest > 100} { set do 100 } else { set do $rest }
380 set bytes [read $data $do]
381 set chunk [list]
382 for {set i 0} {$i < $do} {incr i} {
383 scan [string index $bytes $i] %c v
384 lappend chunk $v
385 }
387 #puts "$chunk = [llength $chunk]"
388 set did [llength $chunk]
389 if {$did != $do} {
390 puts "\n -- Short transfer error!"
391 break
392 }
394 jtag_write_memory $target $chunk
395 set target [expr {$target+$did}]
396 }
398 if {$done == $len} {
399 puts "\r$prompt[format %d $len] bytes - complete"
400 }
402 close $data
403 }
405 proc load {file} {
406 if {$file == ""} {
407 puts "Specify file to load!"
408 return
409 }
411 puts -nonewline "Capturing the CPU at address 0x0: "
412 for {set i 0} {$i < 20} {incr i} {
413 # bi +0 (CPU trap)
414 write_memory 0x0 0xE0000000
415 # flush instruction cache
416 jtag_write_csr 0x3 0x0
417 # Position CPU on this trap
418 jtag_reset
419 }
420 # Wait a bit to be sure the CPU has the trap good and cached
421 after 20
422 puts "done"
424 set sections [list]
425 set sf [open "| readelf -S $file" "r"]
426 while {[gets $sf line] >= 0} {
427 if {[regexp {^\s+\[..\]\s+(\.\w+)\s+[^0-9a-f]*\s[0-9a-f]{4,}\s+([0-9a-f]{4,})\s+([0-9a-f]{4,})\s} $line nil section offset size] == 0} continue
428 lappend sections "$section 0x$offset 0x$size"
429 }
430 close $sf
432 # We can safely overwrite all of the instruction bus (even 0x0) now.
433 # The trap is certainly cached and the CPU will not see the new values.
434 set lf [open "| readelf -l $file" "r"]
435 while {[gets $lf line] >= 0} {
436 if {[regexp {^\s*LOAD\s+(\w+)\s+(\w+)\s+(\w+)\s+(\w+)\s+} $line nil offset vaddr paddr len] == 0} continue
437 puts "Loading $offset+$len to $paddr"
438 if {$paddr != $vaddr} {
439 puts " Physical and virtual address mismatch! - Skipping"
440 continue
441 }
442 foreach j $sections {
443 lassign [split $j " "] section off size
444 if {$offset <= $off && $off+$size <= $offset+$len} {
445 transfer " section $section: " $file $off $size [expr {$paddr+$off-$offset}]
446 } elseif {$offset <= $off && $off < $offset+$len} {
447 puts " section $section: only half contained??"
448 }
449 }
450 }
451 close $lf
453 # The CPU is spinning at address 0, so no need to reset it.
454 # First flush the dcache and then release the CPU by flushing the icache
455 puts -nonewline "Releasing CPU: "
456 jtag_write_csr 0x4 0x0
457 after 20
458 jtag_write_csr 0x3 0x0
459 puts done
460 }
462 ################################ MAIN #################################
465 # List all available programming hardwares, and select the USBBlaster.
466 # (Note: this example assumes only one USBBlaster connected.)
467 puts "Programming Hardwares:"
468 foreach hardware_name [get_hardware_names] {
469 puts $hardware_name
470 if { [string match "USB_Blaster*" $hardware_name] } {
471 set usbblaster_name $hardware_name
472 }
473 }
474 puts "\nSelect JTAG chain connected to $usbblaster_name.\n";
476 # List all devices on the chain, and select the first device on the chain.
477 puts "\nDevices on the JTAG chain:"
478 foreach device_name [get_device_names -hardware_name $usbblaster_name] {
479 puts $device_name
480 if { [string match "@1*" $device_name] } {
481 set test_device $device_name
482 }
483 }
484 puts "\nSelect device: $test_device.\n";
486 # Open device
487 open_device -hardware_name $usbblaster_name -device_name $test_device
489 device_lock -timeout 10000
490 device_virtual_ir_shift -instance_index 0 -ir_value 1 -no_captured_ir_value
492 jtag_sync
493 while {$cmd != "quit"} {
494 puts -nonewline "\nlm32> "
496 if {[gets stdin line] < 0} break
498 if {$line eq ""} { set line $nextcmd }
500 set parts [split $line " "]
501 set args [lassign $parts cmd]
502 set tail [lassign $args arg1 arg2 arg3 arg4]
504 set nextcmd ""
505 switch $cmd {
506 "" { }
507 "break" { jtag_break }
508 "reset" { jtag_reset }
509 "sync" { jtag_sync }
510 "read" { set nextcmd [read_memory $arg1 $arg2] }
511 "dump" { set nextcmd [dump_memory $arg1 $arg2] }
512 "write" { write_memory $arg1 $arg2 }
513 "csr" { jtag_write_csr $arg1 $arg2 }
514 "recv" { jtag_uart_read }
515 "send" { send $args }
516 "load" { load $arg1 }
517 "quit" { }
518 default { puts "Unknown command" }
519 }
520 }
522 # Close device
523 device_unlock
524 puts "Bye!"
525 close_device