Files
risc-v-cpu/pipelined-cpu/tools/play_saolei.tcl
T
Alpha 132c9202f6 feat(saolei): 命令行交互式玩扫雷(无需 VGA 显示器)
- srcs/tb/tb_saolei_play.v:受 cmd.txt 驱动的交互式 TB,每 100us 轮询一个按键字符,
  每 1ms 把显存 dump 到 now.txt
- tools/play_saolei.tcl:xsim 里 k c / k u / k f 一步一按键,自动把 now.txt 画到终端
- saolei/tools/fb2png.py:新增 --term,用 ANSI 24 位色在终端画 40x30 棋盘,光标格反色
- .gitignore:放行 create_project_saolei.tcl
实测:k c 进关卡、k uuuu 光标精确移动 4 格、k c 首击展开出数字 1/2
2026-09-19 19:54:56 +08:00

94 lines
3.9 KiB
Tcl
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# =============================================================================
# play_saolei.tcl —— 没有 VGA 显示器时,在 xsim 命令行里"玩"扫雷
#
# 用法(建议用 source -encoding utf-8 加载本文件,否则 xsim 默认按 GBK 读,中文注释会乱):
# cd <某个空目录,例如 _tmp/saolei_sim>
# xvlog -d SAOLEI_ROM -i <pipelined-cpu/srcs/board> -i <pipelined-cpu/srcs/rtl> \
# <pipelined-cpu/srcs/rtl/*.v> <pipelined-cpu/srcs/board/cpu21_board_top.v> \
# <pipelined-cpu/srcs/tb/tb_saolei_play.v>
# xelab -d SAOLEI_ROM -top tb_saolei_play -snapshot saolei_play
# xsim saolei_play -tclbatch <本脚本绝对路径>
#
# 然后在 xsim 提示符下敲命令(一个字母就是一步,会立刻重画棋盘):
# k c 左键点击(= 板上 BTNC)
# k u / k d / k l / k r 光标 上/下/左/右(也认 w s a d)
# k f 插旗模式点击(点一下插旗,再点取消;= 按住 SW3 再点)
# k p 只切换插旗模式开关(不点击)
# k z 复位(等于重新上电,回到开始界面)
# k uucc 可以连写:上、上、点、点
# shot 不按键,只重画一遍当前画面
# help 键位说明
#
# 原理:k 把字符写进 cmd.txt;tb_saolei_play 每 100 us 仿真时间轮询一次并执行按键,
# 同时每 1 ms 把显存 dump 到 now.txt;k 再调 fb2png.py --term 把画面画到终端。
# 仿真速度大约是 1 ms 仿真时间 = 0.5 s 墙钟,所以每步等 1~2 秒,比真实慢很多,
# 但足够用来验证"这个程序真的能玩"。
# =============================================================================
set script_dir [file dirname [file normalize [info script]]]
set fb2png [file normalize [file join $script_dir .. .. saolei tools fb2png.py]]
# 按键字符 -> 人类可读的动作(只用于回显)
array set KEYNAME {
c "左键点击" u "上" w "上" d "下" s "下"
l "左" a "左" r "右"
f "插旗点击" p "切插旗开关" g "go 键" z "复位"
}
# 每次只把一个字符写进 cmd.txt(TB 每 100 us 读走一个,读完就清空)
proc send_char {c} {
set fh [open "cmd.txt" "w"]
puts -nonewline $fh $c
close $fh
}
# 先确保 cmd.txt 存在,否则 TB 每 100 us 都会刷一条 could not be opened 警告
if {![file exists "cmd.txt"]} {
set fh [open "cmd.txt" "w"]
close $fh
}
# 把 now.txt 渲染到终端(ANSI 彩色棋盘)
proc render {} {
global fb2png
if {![file exists "now.txt"]} {
puts " (now.txt not ready yet - run a bit first)"
return
}
if {[catch { exec py $fb2png --term now.txt >@stdout 2>@stderr } err]} {
puts " render failed: $err"
puts " try manually: py \"$fb2png\" --term now.txt"
}
}
proc help {} {
puts " ---------------- SAOLEI controls (type at the xsim prompt) ----------------"
puts " k c left click (board BTNC)"
puts " k u/d/l/r move cursor up/down/left/right (w/s/a/d work too)"
puts " k f click in flag mode k p toggle flag switch only"
puts " k z reset k uucc several actions at once"
puts " shot redraw help this text quit exit"
puts " PNG screenshot: py \"$::fb2png\" now.txt shot.png"
puts " ---------------------------------------------------------------------------"
}
# one step: send the key -> advance simulation -> redraw
proc k {keys} {
set s [string map {" " "c"} [string tolower $keys]]
foreach ch [split $s ""] {
if {[string length $ch] == 0} { continue }
puts " >> $ch"
send_char $ch
run 1500 us
}
render
}
proc shot {} { render }
# ---- opening: run a little so the start screen is drawn, then show it ----
help
puts "booting... (init + draw start screen)"
run 3 ms
render