[PATCH umr 16/17] gui: add a wave single step button
Nicolai Hähnle
nicolai.haehnle at amd.com
Tue Jun 6 09:17:24 UTC 2023
Signed-off-by: Nicolai Hähnle <nicolai.haehnle at amd.com>
---
src/app/gui/commands.c | 50 +++++++++++++++++++++++++++++++++++++
src/app/gui/waves_panel.cpp | 40 +++++++++++++++++++++++++++++
src/lib/scan_waves.c | 2 +-
src/umr.h | 2 ++
4 files changed, 93 insertions(+), 1 deletion(-)
diff --git a/src/app/gui/commands.c b/src/app/gui/commands.c
index 38ae44d..fb6efa0 100644
--- a/src/app/gui/commands.c
+++ b/src/app/gui/commands.c
@@ -2036,20 +2036,70 @@ JSON_Value *umr_process_json_request(JSON_Object *request, void **raw_data, unsi
answer = json_value_init_object();
waves_to_json(asic, ring_is_halted, 1, json_object(answer));
if (disable_gfxoff && asic->fd.gfxoff >= 0) {
uint32_t value = 1;
write(asic->fd.gfxoff, &value, sizeof(value));
}
if (resume_waves)
umr_sq_cmd_halt_waves(asic, UMR_SQ_CMD_RESUME);
+ } else if (strcmp(command, "singlestep") == 0) {
+ strcpy(asic->options.ring_name, json_object_get_string(request, "ring"));
+
+ unsigned se = (unsigned)json_object_get_number(request, "se");
+ unsigned sh = (unsigned)json_object_get_number(request, "sh");
+ unsigned wgp = (unsigned)json_object_get_number(request, "wgp");
+ unsigned simd_id = (unsigned)json_object_get_number(request, "simd_id");
+ unsigned wave_id = (unsigned)json_object_get_number(request, "wave_id");
+
+ asic->options.skip_gprs = 0;
+ asic->options.verbose = 0;
+
+ struct umr_wave_data wd;
+ memset(&wd, 0, sizeof(wd));
+
+ int r = umr_scan_wave_slot(asic, se, sh, wgp, simd_id, wave_id, &wd);
+ if (r < 0) {
+ last_error = "failed to scan wave slot";
+ goto error;
+ }
+
+ // Send the single-step command in a limited retry loop because a small number of
+ // single-step commands are required before an instruction is actually issued after
+ // a branch.
+ for (int retry = 0; r == 1 && retry < 5; ++retry) {
+ umr_sq_cmd_singlestep(asic, se, sh, wgp, simd_id, wave_id);
+
+ struct umr_wave_data new_wd;
+ memset(&new_wd, 0, sizeof(new_wd));
+
+ r = umr_scan_wave_slot(asic, se, sh, wgp, simd_id, wave_id, &new_wd);
+ if (r < 0) {
+ last_error = "failed to scan wave slot";
+ goto error;
+ }
+
+ bool moved = new_wd.ws.pc_lo != wd.ws.pc_lo || new_wd.ws.pc_hi != wd.ws.pc_hi;
+ memcpy(&wd, &new_wd, sizeof(wd));
+ if (moved)
+ break;
+ }
+
+ answer = json_value_init_object();
+
+ if (r == 1) {
+ JSON_Value *shaders = json_value_init_object();
+ JSON_Value *wave = wave_to_json(asic, &wd, 1, /* todo: stream */NULL, shaders);
+ json_object_set_value(json_object(answer), "wave", wave);
+ json_object_set_value(json_object(answer), "shaders", shaders);
+ }
} else if (strcmp(command, "resume-waves") == 0) {
strcpy(asic->options.ring_name, json_object_get_string(request, "ring"));
umr_sq_cmd_halt_waves(asic, UMR_SQ_CMD_RESUME);
answer = json_value_init_object();
} else if (strcmp(command, "ring") == 0) {
char *ring_name = (char*)json_object_get_string(request, "ring");
uint32_t wptr, rptr, drv_wptr, ringsize, value, *ring_data;
int halt_waves = json_object_get_boolean(request, "halt_waves");
enum umr_ring_type rt;
asic->options.halt_waves = halt_waves;
diff --git a/src/app/gui/waves_panel.cpp b/src/app/gui/waves_panel.cpp
index 7e13b48..68b06ea 100644
--- a/src/app/gui/waves_panel.cpp
+++ b/src/app/gui/waves_panel.cpp
@@ -106,21 +106,38 @@ public:
JSON_Array *waves_array = json_object_get_array(json_object(answer), "waves");
int wave_count = json_array_get_count(waves_array);
for (int i = 0; i < wave_count; ++i) {
JSON_Object *wave = json_object(json_value_deep_copy(json_array_get_value(waves_array, i)));
waves.emplace_back(get_wave_id(wave), wave);
}
JSON_Object *shaders_dict = json_object_get_object(json_object(answer), "shaders");
update_shaders(shaders_dict);
+ } else if (strcmp(command, "singlestep") == 0) {
+ JSON_Object *wave = json_object(json_value_deep_copy(json_object_get_value(json_object(answer), "wave")));
+ std::string id = get_wave_id(wave ? wave : request);
+ size_t i = find_wave_by_id(id);
+ if (i < waves.size()) {
+ json_value_free(json_object_get_wrapping_value(waves[i].wave));
+ if (wave) {
+ waves[i].wave = wave;
+ } else {
+ waves.erase(waves.begin() + i);
+ }
+ } else {
+ if (wave)
+ waves.emplace_back(id, wave);
}
+
+ JSON_Object *shaders_dict = json_object_get_object(json_object(answer), "shaders");
+ update_shaders(shaders_dict);
} else {
return; // should be handled by a different panel
}
}
bool display(float dt, const ImVec2& avail, bool can_send_request) {
ImGui::Checkbox("Disable gfxoff", &turn_off_gfxoff);
ImGui::SameLine();
ImGui::Checkbox("Halt waves", &halt);
if (halt) {
@@ -185,20 +202,29 @@ public:
ImGui::Columns(1);
ImGui::Separator();
ImGui::NextColumn();
ImGui::Text("PC: #b589000x%" PRIx64, (uint64_t)json_object_get_number(wave, "PC"));
if (shader_address_str) {
ImGui::SameLine();
if (ImGui::Button("View Shader")) {
active_shader_wave = waves[i].id;
force_scroll = true;
}
+ if (asic->family >= FAMILY_NV) {
+ ImGui::SameLine();
+ ImGui::BeginDisabled(!can_send_request);
+ if (ImGui::Button("Single step")) {
+ active_shader_wave = waves[i].id;
+ send_singlestep_command(waves[i].wave);
+ }
+ ImGui::EndDisabled();
+ }
} else {
}
ImGui::NextColumn();
if (ImGui::TreeNodeEx("Status")) {
ImGui::Columns(4);
size_t n = json_object_get_count(status);
for (size_t j = 0; j < n; j++) {
ImGui::Text("%s: #b58900%d", json_object_get_name(status, j),
(unsigned)json_number(json_object_get_value_at(status, j)));
ImGui::NextColumn();
@@ -436,20 +462,34 @@ public:
private:
void send_waves_command(bool halt_waves, bool resume_waves, bool disable_gfxoff) {
JSON_Value *req = json_value_init_object();
json_object_set_string(json_object(req), "command", "waves");
json_object_set_boolean(json_object(req), "halt_waves", halt_waves);
json_object_set_boolean(json_object(req), "resume_waves", halt_waves && resume_waves);
json_object_set_boolean(json_object(req), "disable_gfxoff", disable_gfxoff);
json_object_set_string(json_object(req), "ring", asic->family >= FAMILY_NV ? "gfx_0.0.0" : "gfx");
send_request(req);
}
+
+ void send_singlestep_command(JSON_Object *wave) {
+ assert(asic->family >= FAMILY_NV);
+ JSON_Value *req = json_value_init_object();
+ json_object_set_string(json_object(req), "command", "singlestep");
+ json_object_set_string(json_object(req), "ring", asic->family >= FAMILY_NV ? "gfx_0.0.0" : "gfx");
+ json_object_set_number(json_object(req), "se", json_object_get_number(wave, "se"));
+ json_object_set_number(json_object(req), "sh", json_object_get_number(wave, "sh"));
+ json_object_set_number(json_object(req), "wgp", json_object_get_number(wave, "wgp"));
+ json_object_set_number(json_object(req), "simd_id", json_object_get_number(wave, "simd_id"));
+ json_object_set_number(json_object(req), "wave_id", json_object_get_number(wave, "wave_id"));
+ send_request(req);
+ }
+
private:
struct Wave {
std::string id; // "seN.saN.etc"
JSON_Object *wave;
bool vgpr_show[512] = {};
int vgpr_view[512] = {};
Wave(std::string id, JSON_Object *wave) : id(id), wave(wave) {}
};
diff --git a/src/lib/scan_waves.c b/src/lib/scan_waves.c
index ca1d9fb..533c5d0 100644
--- a/src/lib/scan_waves.c
+++ b/src/lib/scan_waves.c
@@ -530,21 +530,21 @@ int umr_parse_wave_data_gfx(struct umr_asic *asic, struct umr_wave_status *ws, c
else
return umr_parse_wave_data_gfx_10_11(asic, ws, buf);
}
/**
* Scan the given wave slot. Return true and fill in \p pwd if a wave is present.
* Otherwise, return false.
*
* \param cu the CU on <=gfx9, the WGP on >=gfx10
*/
-static int umr_scan_wave_slot(struct umr_asic *asic, uint32_t se, uint32_t sh, uint32_t cu,
+int umr_scan_wave_slot(struct umr_asic *asic, uint32_t se, uint32_t sh, uint32_t cu,
uint32_t simd, uint32_t wave, struct umr_wave_data *pwd)
{
unsigned thread, num_threads;
int r;
if (asic->family <= FAMILY_AI)
r = asic->wave_funcs.get_wave_status(asic, se, sh, cu, simd, wave, &pwd->ws);
else
r = asic->wave_funcs.get_wave_status(asic, se, sh, MANY_TO_INSTANCE(cu, simd), 0, wave, &pwd->ws);
diff --git a/src/umr.h b/src/umr.h
index 8981986..030124f 100644
--- a/src/umr.h
+++ b/src/umr.h
@@ -1392,20 +1392,22 @@ void umr_free_maps(struct umr_asic *asic);
void umr_close_asic(struct umr_asic *asic); // call this to close a fully open asic
int umr_query_drm(struct umr_asic *asic, int field, void *ret, int size);
int umr_query_drm_vbios(struct umr_asic *asic, int field, int type, void *ret, int size);
int umr_update(struct umr_asic *asic, char *script);
int umr_update_string(struct umr_asic *asic, char *sdata);
/* lib helpers */
uint32_t umr_get_ip_revision(struct umr_asic *asic, const char *ipname);
int umr_get_wave_status(struct umr_asic *asic, unsigned se, unsigned sh, unsigned cu, unsigned simd, unsigned wave, struct umr_wave_status *ws);
struct umr_wave_data *umr_scan_wave_data(struct umr_asic *asic);
+int umr_scan_wave_slot(struct umr_asic *asic, uint32_t se, uint32_t sh, uint32_t cu,
+ uint32_t simd, uint32_t wave, struct umr_wave_data *pwd);
int umr_read_wave_status_via_mmio_gfx8_9(struct umr_asic *asic, uint32_t simd, uint32_t wave, uint32_t *dst, int *no_fields);
int umr_read_wave_status_via_mmio_gfx_10_11(struct umr_asic *asic, uint32_t wave, uint32_t *dst, int *no_fields);
int umr_parse_wave_data_gfx(struct umr_asic *asic, struct umr_wave_status *ws, const uint32_t *buf);
int umr_get_wave_sq_info_vi(struct umr_asic *asic, unsigned se, unsigned sh, unsigned cu, struct umr_wave_status *ws);
int umr_get_wave_sq_info(struct umr_asic *asic, unsigned se, unsigned sh, unsigned cu, struct umr_wave_status *ws);
int umr_read_sgprs(struct umr_asic *asic, struct umr_wave_status *ws, uint32_t *dst);
int umr_read_vgprs(struct umr_asic *asic, struct umr_wave_status *ws, uint32_t thread, uint32_t *dst);
int umr_read_sensor(struct umr_asic *asic, int sensor, void *dst, int *size);
/* mmio helpers */
--
2.40.0
More information about the amd-gfx
mailing list