[PATCH umr 16/17] gui: add a wave single step button

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Signed-off-by: Nicolai Hähnle <nicolai.haehnle@xxxxxxx>
---
 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




[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux