nOS-V Breakdown
This commit is contained in:
		
							parent
							
								
									92cc779caf
								
							
						
					
					
						commit
						9fb53df45d
					
				
							
								
								
									
										44
									
								
								cfg/cpu/nosv/breakdown.cfg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								cfg/cpu/nosv/breakdown.cfg
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,44 @@ | ||||
| #ParaverCFG | ||||
| ConfigFile.Version: 3.4 | ||||
| ConfigFile.NumWindows: 1 | ||||
| 
 | ||||
| 
 | ||||
| ################################################################################ | ||||
| < NEW DISPLAYING WINDOW CPU: nOS-V Runtime/Idle/Task breakdown > | ||||
| ################################################################################ | ||||
| window_name CPU: nOS-V Runtime/Idle/Task breakdown | ||||
| window_type single | ||||
| window_id 1 | ||||
| window_position_x 0 | ||||
| window_position_y 0 | ||||
| window_width 600 | ||||
| window_height 150 | ||||
| window_comm_lines_enabled false | ||||
| window_flags_enabled false | ||||
| window_noncolor_mode true | ||||
| window_custom_color_enabled true | ||||
| window_custom_color_palette {1.000000000000:0,70,0},{3.000000000000:99,131,0},{4.000000000000:53,121,221},{5.000000000000:223,108,0},{6.000000000000:75,127,82},{7.000000000000:242,110,162},{8.000000000000:255,190,0},{9.000000000000:153,114,0},{10.000000000000:156,12,231},{11.000000000000:177,25,229},{12.000000000000:255,72,50},{15.000000000000:0,171,255},{16.000000000000:124,213,228},{17.000000000000:242,239,141},{18.000000000000:80,80,80},{19.000000000000:94,0,0},{20.000000000000:128,165,214},{22.000000000000:222,101,128},{23.000000000000:110,148,255},{100.000000000000:0,100,0},{101.000000000000:100,100,177},{102.000000000000:150,150,0} | ||||
| window_logical_filtered true | ||||
| window_physical_filtered false | ||||
| window_comm_fromto true | ||||
| window_comm_tagsize true | ||||
| window_comm_typeval true | ||||
| window_units Microseconds | ||||
| window_maximum_y 1000.0 | ||||
| window_minimum_y 1.0 | ||||
| window_compute_y_max true | ||||
| window_level thread | ||||
| window_scale_relative 1.000000000000 | ||||
| window_end_time_relative 1.000000000000 | ||||
| window_object appl { 1, { All } } | ||||
| window_begin_time_relative 0.000000000000 | ||||
| window_open true | ||||
| window_drawmode draw_randnotzero | ||||
| window_drawmode_rows draw_randnotzero | ||||
| window_pixel_size 1 | ||||
| window_labels_to_draw 1 | ||||
| window_selected_functions { 14, { {cpu, Active Thd}, {appl, Adding}, {task, Adding}, {thread, Last Evt Val}, {node, Adding}, {system, Adding}, {workload, Adding}, {from_obj, All}, {to_obj, All}, {tag_msg, All}, {size_msg, All}, {bw_msg, All}, {evt_type, =}, {evt_value, All} } } | ||||
| window_compose_functions { 9, { {compose_cpu, As Is}, {compose_appl, As Is}, {compose_task, As Is}, {compose_thread, As Is}, {compose_node, As Is}, {compose_system, As Is}, {compose_workload, As Is}, {topcompose1, As Is}, {topcompose2, As Is} } } | ||||
| window_filter_module evt_type 1 17 | ||||
| window_filter_module evt_type_label 1 "CPU: nOS-V Runtime/Idle/Task breakdown" | ||||
| 
 | ||||
							
								
								
									
										44
									
								
								cfg/cpu/nosv/idle.cfg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								cfg/cpu/nosv/idle.cfg
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,44 @@ | ||||
| #ParaverCFG | ||||
| ConfigFile.Version: 3.4 | ||||
| ConfigFile.NumWindows: 1 | ||||
| 
 | ||||
| 
 | ||||
| ################################################################################ | ||||
| < NEW DISPLAYING WINDOW CPU: nOS-V idle state of the RUNNING thread > | ||||
| ################################################################################ | ||||
| window_name CPU: nOS-V idle state of the RUNNING thread | ||||
| window_type single | ||||
| window_id 1 | ||||
| window_position_x 0 | ||||
| window_position_y 0 | ||||
| window_width 600 | ||||
| window_height 150 | ||||
| window_comm_lines_enabled false | ||||
| window_flags_enabled false | ||||
| window_noncolor_mode true | ||||
| window_custom_color_enabled true | ||||
| window_custom_color_palette {100.000000000000:0,100,0},{101.000000000000:100,100,177},{102.000000000000:150,150,0} | ||||
| window_logical_filtered true | ||||
| window_physical_filtered false | ||||
| window_comm_fromto true | ||||
| window_comm_tagsize true | ||||
| window_comm_typeval true | ||||
| window_units Microseconds | ||||
| window_maximum_y 1000.0 | ||||
| window_minimum_y 1.0 | ||||
| window_compute_y_max true | ||||
| window_level thread | ||||
| window_scale_relative 1.000000000000 | ||||
| window_end_time_relative 1.000000000000 | ||||
| window_object appl { 1, { All } } | ||||
| window_begin_time_relative 0.000000000000 | ||||
| window_open true | ||||
| window_drawmode draw_randnotzero | ||||
| window_drawmode_rows draw_randnotzero | ||||
| window_pixel_size 1 | ||||
| window_labels_to_draw 1 | ||||
| window_selected_functions { 14, { {cpu, Active Thd}, {appl, Adding}, {task, Adding}, {thread, Last Evt Val}, {node, Adding}, {system, Adding}, {workload, Adding}, {from_obj, All}, {to_obj, All}, {tag_msg, All}, {size_msg, All}, {bw_msg, All}, {evt_type, =}, {evt_value, All} } } | ||||
| window_compose_functions { 9, { {compose_cpu, As Is}, {compose_appl, As Is}, {compose_task, As Is}, {compose_thread, As Is}, {compose_node, As Is}, {compose_system, As Is}, {compose_workload, As Is}, {topcompose1, As Is}, {topcompose2, As Is} } } | ||||
| window_filter_module evt_type 1 16 | ||||
| window_filter_module evt_type_label 1 "CPU: nOS-V idle state of the RUNNING thread" | ||||
| 
 | ||||
| @ -52,6 +52,7 @@ add_library(emu STATIC | ||||
|   nanos6/setup.c | ||||
|   nanos6/event.c | ||||
|   nanos6/breakdown.c | ||||
|   nosv/breakdown.c | ||||
|   nosv/setup.c | ||||
|   nosv/event.c | ||||
|   nodes/setup.c | ||||
|  | ||||
| @ -19,6 +19,8 @@ enum emu_prv_types { | ||||
| 	PRV_NOSV_SUBSYSTEM   = 13, | ||||
| 	PRV_NOSV_RANK        = 14, | ||||
| 	PRV_NOSV_BODYID      = 15, | ||||
| 	PRV_NOSV_IDLE        = 16, | ||||
| 	PRV_NOSV_BREAKDOWN   = 17, | ||||
| 	PRV_TAMPI_SUBSYSTEM  = 20, | ||||
| 	PRV_MPI_FUNCTION     = 25, | ||||
| 	PRV_NODES_SUBSYSTEM  = 30, | ||||
|  | ||||
							
								
								
									
										312
									
								
								src/emu/nosv/breakdown.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										312
									
								
								src/emu/nosv/breakdown.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,312 @@ | ||||
| /* Copyright (c) 2023 Barcelona Supercomputing Center (BSC)
 | ||||
|  * SPDX-License-Identifier: GPL-3.0-or-later */ | ||||
| 
 | ||||
| #include "breakdown.h" | ||||
| #include <stdint.h> | ||||
| #include <stdio.h> | ||||
| #include "bay.h" | ||||
| #include "chan.h" | ||||
| #include "common.h" | ||||
| #include "cpu.h" | ||||
| #include "emu.h" | ||||
| #include "emu_args.h" | ||||
| #include "emu_prv.h" | ||||
| #include "extend.h" | ||||
| #include "model_cpu.h" | ||||
| #include "mux.h" | ||||
| #include "nosv_priv.h" | ||||
| #include "proc.h" | ||||
| #include "pv/pcf.h" | ||||
| #include "pv/prf.h" | ||||
| #include "pv/prv.h" | ||||
| #include "pv/pvt.h" | ||||
| #include "recorder.h" | ||||
| #include "sort.h" | ||||
| #include "system.h" | ||||
| #include "task.h" | ||||
| #include "track.h" | ||||
| #include "value.h" | ||||
| 
 | ||||
| 
 | ||||
| static int | ||||
| create_cpu(struct bay *bay, struct nosv_breakdown_cpu *bcpu, int64_t gindex) | ||||
| { | ||||
| 	enum chan_type t = CHAN_SINGLE; | ||||
| 	chan_init(&bcpu->tr,  t, "nosv.cpu%ld.breakdown.tr",  gindex); | ||||
| 	chan_init(&bcpu->tri, t, "nosv.cpu%ld.breakdown.tri", gindex); | ||||
| 
 | ||||
| 	/* Register all channels in the bay */ | ||||
| 	if (bay_register(bay, &bcpu->tr) != 0) { | ||||
| 		err("bay_register tr failed"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 	if (bay_register(bay, &bcpu->tri) != 0) { | ||||
| 		err("bay_register tri failed"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int | ||||
| model_nosv_breakdown_create(struct emu *emu) | ||||
| { | ||||
| 	if (emu->args.breakdown == 0) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	struct nosv_emu *memu = EXT(emu, 'V'); | ||||
| 	struct nosv_breakdown_emu *bemu = &memu->breakdown; | ||||
| 
 | ||||
| 	/* Count phy cpus */ | ||||
| 	struct system *sys = &emu->system; | ||||
| 	int64_t nphycpus = sys->ncpus - sys->nlooms; | ||||
| 	bemu->nphycpus = nphycpus; | ||||
| 
 | ||||
| 	/* Create a new Paraver trace */ | ||||
| 	struct recorder *rec = &emu->recorder; | ||||
| 	bemu->pvt = recorder_add_pvt(rec, "nosv-breakdown", nphycpus); | ||||
| 	if (bemu->pvt == NULL) { | ||||
| 		err("recorder_add_pvt failed"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	if (sort_init(&bemu->sort, &emu->bay, nphycpus, "nosv.breakdown.sort") != 0) { | ||||
| 		err("sort_init failed"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	for (struct cpu *cpu = sys->cpus; cpu; cpu = cpu->next) { | ||||
| 		if (cpu->is_virtual) | ||||
| 			continue; | ||||
| 
 | ||||
| 		struct nosv_cpu *mcpu = EXT(cpu, 'V'); | ||||
| 		struct nosv_breakdown_cpu *bcpu = &mcpu->breakdown; | ||||
| 
 | ||||
| 		if (create_cpu(&emu->bay, bcpu, cpu->gindex) != 0) { | ||||
| 			err("create_cpu failed"); | ||||
| 			return -1; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| select_tr(struct mux *mux, struct value value, struct mux_input **input) | ||||
| { | ||||
| 	/* Only select the task if we are in ST_TASK_BODY and the task_type has
 | ||||
| 	 * a non-null value */ | ||||
| 
 | ||||
| 	int64_t in_body = (value.type == VALUE_INT64 && value.i == ST_TASK_BODY); | ||||
| 
 | ||||
| 	if (in_body) { | ||||
| 		struct value tt; | ||||
| 		struct mux_input *ttinput = mux_get_input(mux, 1); | ||||
| 		if (chan_read(ttinput->chan, &tt) != 0) { | ||||
| 			err("chan_read failed"); | ||||
| 			return -1; | ||||
| 		} | ||||
| 
 | ||||
| 		/* Only show task type if we have a task */ | ||||
| 		if (tt.type == VALUE_NULL) | ||||
| 			in_body = 0; | ||||
| 	} | ||||
| 
 | ||||
| 	if (!in_body) { | ||||
| 		/* Only select ss if not NULL */ | ||||
| 		struct value ss; | ||||
| 		struct mux_input *ssinput = mux_get_input(mux, 0); | ||||
| 		if (chan_read(ssinput->chan, &ss) != 0) { | ||||
| 			err("chan_read failed"); | ||||
| 			return -1; | ||||
| 		} | ||||
| 
 | ||||
| 		/* Don't select anything, so the default output is shown */ | ||||
| 		if (ss.type == VALUE_NULL) { | ||||
| 			dbg("not selecting anything"); | ||||
| 			*input = NULL; | ||||
| 			return 0; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	int64_t i = in_body; | ||||
| 	char *inputs[] = { "subsystem", "task_type" }; | ||||
| 	dbg("selecting input %ld (%s)", i, inputs[i]); | ||||
| 	*input = mux_get_input(mux, i); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| select_idle(struct mux *mux, struct value value, struct mux_input **input) | ||||
| { | ||||
| 	dbg("selecting tri output for value %s", value_str(value)); | ||||
| 
 | ||||
| 	if (value.type == VALUE_INT64 && value.i == ST_PROGRESSING) { | ||||
| 		dbg("selecting input 0 (tr)"); | ||||
| 		*input = mux_get_input(mux, 0); | ||||
| 	} else { | ||||
| 		dbg("selecting input 1 (idle)"); | ||||
| 		*input = mux_get_input(mux, 1); | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| connect_cpu(struct bay *bay, struct nosv_cpu *mcpu) | ||||
| { | ||||
| 	struct nosv_breakdown_cpu *bcpu = &mcpu->breakdown; | ||||
| 
 | ||||
| 	/* Channel aliases */ | ||||
| 	struct chan *ss = &mcpu->m.track[CH_SUBSYSTEM].ch; | ||||
| 	struct chan *tt = &mcpu->m.track[CH_TYPE].ch; | ||||
| 	struct chan *idle = &mcpu->m.track[CH_IDLE].ch; | ||||
| 	struct chan *tr = &bcpu->tr; | ||||
| 	struct chan *tri = &bcpu->tri; | ||||
| 
 | ||||
| 	/* Connect mux0 using ss as select */ | ||||
| 	if (mux_init(&bcpu->mux0, bay, ss, tr, select_tr, 2) != 0) { | ||||
| 		err("mux_init failed"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	if (mux_set_input(&bcpu->mux0, 0, ss) != 0) { | ||||
| 		err("mux_set_input ss failed"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	if (mux_set_input(&bcpu->mux0, 1, tt) != 0) { | ||||
| 		err("mux_set_input tt failed"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	/* TODO what do we emit on null? */ | ||||
| 	mux_set_default(&bcpu->mux0, value_int64(666)); | ||||
| 
 | ||||
| 	/* Connect mux 1 using idle as select */ | ||||
| 	if (mux_init(&bcpu->mux1, bay, idle, tri, select_idle, 2) != 0) { | ||||
| 		err("mux_init failed"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	if (mux_set_input(&bcpu->mux1, 0, tr) != 0) { | ||||
| 		err("mux_set_input tr failed"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	if (mux_set_input(&bcpu->mux1, 1, idle) != 0) { | ||||
| 		err("mux_set_input idle failed"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int | ||||
| model_nosv_breakdown_connect(struct emu *emu) | ||||
| { | ||||
| 	if (emu->args.breakdown == 0) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	struct nosv_emu *memu = EXT(emu, 'V'); | ||||
| 	struct nosv_breakdown_emu *bemu = &memu->breakdown; | ||||
| 	struct bay *bay = &emu->bay; | ||||
| 	struct system *sys = &emu->system; | ||||
| 
 | ||||
| 	int64_t i = 0; | ||||
| 	for (struct cpu *cpu = sys->cpus; cpu; cpu = cpu->next) { | ||||
| 		if (cpu->is_virtual) | ||||
| 			continue; | ||||
| 
 | ||||
| 		struct nosv_cpu *mcpu = EXT(cpu, 'V'); | ||||
| 		struct nosv_breakdown_cpu *bcpu = &mcpu->breakdown; | ||||
| 
 | ||||
| 		/* Connect tr and tri channels and muxes */ | ||||
| 		if (connect_cpu(bay, mcpu) != 0) { | ||||
| 			err("connect_cpu failed"); | ||||
| 			return -1; | ||||
| 		} | ||||
| 
 | ||||
| 		/* Connect tri to sort */ | ||||
| 		if (sort_set_input(&bemu->sort, i, &bcpu->tri) != 0) { | ||||
| 			err("sort_set_input failed"); | ||||
| 			return -1; | ||||
| 		} | ||||
| 
 | ||||
| 		/* Connect out to PRV */ | ||||
| 		struct prv *prv = pvt_get_prv(bemu->pvt); | ||||
| 		long type = PRV_NOSV_BREAKDOWN; | ||||
| 		long flags = PRV_SKIPDUP | PRV_ZERO; | ||||
| 
 | ||||
| 		struct chan *out = sort_get_output(&bemu->sort, i); | ||||
| 		if (prv_register(prv, i, type, bay, out, flags)) { | ||||
| 			err("prv_register failed"); | ||||
| 			return -1; | ||||
| 		} | ||||
| 
 | ||||
| 		i++; | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int | ||||
| model_nosv_breakdown_finish(struct emu *emu, | ||||
| 		const struct pcf_value_label **labels) | ||||
| { | ||||
| 	if (emu->args.breakdown == 0) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	struct nosv_emu *memu = EXT(emu, 'V'); | ||||
| 	struct nosv_breakdown_emu *bemu = &memu->breakdown; | ||||
| 	struct pcf *pcf = pvt_get_pcf(bemu->pvt); | ||||
| 	long typeid = PRV_NOSV_BREAKDOWN; | ||||
| 	char label[] = "CPU: nOS-V Runtime/Idle/Task breakdown"; | ||||
| 	struct pcf_type *pcftype = pcf_add_type(pcf, typeid, label); | ||||
| 	const struct pcf_value_label *v = NULL; | ||||
| 
 | ||||
| 	/* Emit subsystem values */ | ||||
| 	for (v = labels[CH_SUBSYSTEM]; v->label; v++) { | ||||
| 		if (pcf_add_value(pcftype, v->value, v->label) == NULL) { | ||||
| 			err("pcf_add_value ss failed"); | ||||
| 			return -1; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	/* Emit idle values */ | ||||
| 	for (v = labels[CH_IDLE]; v->label; v++) { | ||||
| 		if (pcf_add_value(pcftype, v->value, v->label) == NULL) { | ||||
| 			err("pcf_add_value idle failed"); | ||||
| 			return -1; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	/* Emit task_type values */ | ||||
| 	struct system *sys = &emu->system; | ||||
| 	for (struct proc *p = sys->procs; p; p = p->gnext) { | ||||
| 		struct nosv_proc *proc = EXT(p, 'V'); | ||||
| 		struct task_info *info = &proc->task_info; | ||||
| 		if (task_create_pcf_types(pcftype, info->types) != 0) { | ||||
| 			err("task_create_pcf_types failed"); | ||||
| 			return -1; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	/* Also populate the row labels */ | ||||
| 	struct prf *prf = pvt_get_prf(bemu->pvt); | ||||
| 	for (int64_t row = 0; row < bemu->nphycpus; row++) { | ||||
| 		char name[128]; | ||||
| 		if (snprintf(name, 128, "~CPU %4ld", bemu->nphycpus - row) >= 128) { | ||||
| 			err("label too long"); | ||||
| 			return -1; | ||||
| 		} | ||||
| 
 | ||||
| 		if (prf_add(prf, row, name) != 0) { | ||||
| 			err("prf_add failed for %s", name); | ||||
| 			return -1; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
							
								
								
									
										56
									
								
								src/emu/nosv/breakdown.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								src/emu/nosv/breakdown.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,56 @@ | ||||
| /* Copyright (c) 2023 Barcelona Supercomputing Center (BSC)
 | ||||
|  * SPDX-License-Identifier: GPL-3.0-or-later */ | ||||
| 
 | ||||
| #ifndef BREAKDOWN_H | ||||
| #define BREAKDOWN_H | ||||
| 
 | ||||
| /*
 | ||||
|  * The breakdown model is implemented on top of the CPU subsystem, task_type and | ||||
|  * idle channels. The first mux0 selects the task type when the subsystem | ||||
|  * matches "Task body" otherwise forwards the subsystem as-is to tr. The second | ||||
|  * mux1 selects tr only when the CPU is not Idle, otherwise sets the output tri | ||||
|  * as Idle. | ||||
|  * | ||||
|  *            +--------+ | ||||
|  *            |        | | ||||
|  *            |        v | ||||
|  *            |     +------+ | ||||
|  * subsystem -+-->--|      | | ||||
|  *                  | mux0 |              +------+ | ||||
|  * task_type ---->--|      |-->-- tr -->--|      | | ||||
|  *                  +------+              | mux1 |-->-- tri | ||||
|  * idle --------->-------------------+->--|      | | ||||
|  *                                   |    +------+ | ||||
|  *                                   |        ^ | ||||
|  *                                   |        | | ||||
|  *                                   +--------+ | ||||
|  * | ||||
|  * Then the sort module takes the output tri of each CPU and sorts the values | ||||
|  * which are propagated to the PRV directly. | ||||
|  * | ||||
|  *                 +------+       +-----+ | ||||
|  * cpu0.tri --->---|      |--->---|     | | ||||
|  * ...             | sort |  ...  | PRV | | ||||
|  * cpuN.tri --->---|      |--->---|     | | ||||
|  *                 +------+       +-----+ | ||||
|  */ | ||||
| 
 | ||||
| #include <stdint.h> | ||||
| #include "chan.h" | ||||
| #include "mux.h" | ||||
| #include "sort.h" | ||||
| 
 | ||||
| struct nosv_breakdown_cpu { | ||||
| 	struct mux  mux0; | ||||
| 	struct chan tr; | ||||
| 	struct mux  mux1; | ||||
| 	struct chan tri; | ||||
| }; | ||||
| 
 | ||||
| struct nosv_breakdown_emu { | ||||
| 	int64_t nphycpus; | ||||
| 	struct sort sort; | ||||
| 	struct pvt *pvt; | ||||
| }; | ||||
| 
 | ||||
| #endif /* BREAKDOWN_H */ | ||||
| @ -16,7 +16,7 @@ | ||||
| #include "thread.h" | ||||
| #include "value.h" | ||||
| 
 | ||||
| enum { PUSH = 1, POP = 2, IGN = 3 }; | ||||
| enum { PUSH = 1, POP = 2, SET = 3, IGN = 4 }; | ||||
| 
 | ||||
| #define CHSS CH_SUBSYSTEM | ||||
| 
 | ||||
| @ -77,6 +77,11 @@ static const int ss_table[256][256][3] = { | ||||
| 		['d'] = { CHSS, PUSH, ST_DELEGATE }, | ||||
| 		['D'] = { CHSS, POP,  ST_DELEGATE }, | ||||
| 	}, | ||||
| 	['P'] = { | ||||
| 		['p'] = { CH_IDLE, SET, ST_PROGRESSING }, | ||||
| 		['r'] = { CH_IDLE, SET, ST_RESTING }, | ||||
| 		['a'] = { CH_IDLE, SET, ST_ABSORBING }, | ||||
| 	}, | ||||
| }; | ||||
| 
 | ||||
| static int | ||||
| @ -94,6 +99,8 @@ simple(struct emu *emu) | ||||
| 		return chan_push(ch, value_int64(st)); | ||||
| 	} else if (action == POP) { | ||||
| 		return chan_pop(ch, value_int64(st)); | ||||
| 	} else if (action == SET) { | ||||
| 		return chan_set(ch, value_int64(st)); | ||||
| 	} else if (action == IGN) { | ||||
| 		return 0; /* do nothing */ | ||||
| 	} else { | ||||
| @ -574,6 +581,7 @@ process_ev(struct emu *emu) | ||||
| 		case 'M': | ||||
| 		case 'H': | ||||
| 		case 'A': | ||||
| 		case 'P': | ||||
| 			return simple(emu); | ||||
| 		case 'T': | ||||
| 			return pre_task(emu); | ||||
|  | ||||
| @ -4,6 +4,7 @@ | ||||
| #ifndef NOSV_PRIV_H | ||||
| #define NOSV_PRIV_H | ||||
| 
 | ||||
| #include "breakdown.h" | ||||
| #include "emu.h" | ||||
| #include "task.h" | ||||
| #include "model_cpu.h" | ||||
| @ -18,6 +19,7 @@ enum nosv_chan { | ||||
| 	CH_APPID, | ||||
| 	CH_SUBSYSTEM, | ||||
| 	CH_RANK, | ||||
| 	CH_IDLE, | ||||
| 	CH_MAX, | ||||
| }; | ||||
| 
 | ||||
| @ -56,16 +58,36 @@ struct nosv_thread { | ||||
| 
 | ||||
| struct nosv_cpu { | ||||
| 	struct model_cpu m; | ||||
| 	struct nosv_breakdown_cpu breakdown; | ||||
| }; | ||||
| 
 | ||||
| struct nosv_proc { | ||||
| 	struct task_info task_info; | ||||
| }; | ||||
| 
 | ||||
| struct nosv_emu { | ||||
| 	int connected; | ||||
| 	int event; | ||||
| 	struct nosv_breakdown_emu breakdown; | ||||
| }; | ||||
| 
 | ||||
| enum nosv_progress { | ||||
| 	/* Can mix with subsystem values */ | ||||
| 	ST_PROGRESSING = 100, | ||||
| 	ST_RESTING, | ||||
| 	ST_ABSORBING, | ||||
| }; | ||||
| 
 | ||||
| int model_nosv_probe(struct emu *emu); | ||||
| int model_nosv_create(struct emu *emu); | ||||
| int model_nosv_connect(struct emu *emu); | ||||
| int model_nosv_event(struct emu *emu); | ||||
| int model_nosv_finish(struct emu *emu); | ||||
| 
 | ||||
| int model_nosv_breakdown_create(struct emu *emu); | ||||
| int model_nosv_breakdown_connect(struct emu *emu); | ||||
| int model_nosv_breakdown_finish(struct emu *emu, | ||||
| 		const struct pcf_value_label **labels); | ||||
| 
 | ||||
| 
 | ||||
| #endif /* NOSV_PRIV_H */ | ||||
|  | ||||
| @ -5,6 +5,7 @@ | ||||
| #include <stddef.h> | ||||
| #include <stdlib.h> | ||||
| #include "chan.h" | ||||
| #include "cpu.h" | ||||
| #include "common.h" | ||||
| #include "emu.h" | ||||
| #include "emu_args.h" | ||||
| @ -96,6 +97,7 @@ static const char *chan_name[CH_MAX] = { | ||||
| 	[CH_APPID]     = "appid", | ||||
| 	[CH_SUBSYSTEM] = "subsystem", | ||||
| 	[CH_RANK]      = "rank", | ||||
| 	[CH_IDLE]      = "idle", | ||||
| }; | ||||
| 
 | ||||
| static const int chan_stack[CH_MAX] = { | ||||
| @ -121,6 +123,7 @@ static const int pvt_type[CH_MAX] = { | ||||
| 	[CH_APPID]     = PRV_NOSV_APPID, | ||||
| 	[CH_SUBSYSTEM] = PRV_NOSV_SUBSYSTEM, | ||||
| 	[CH_RANK]      = PRV_NOSV_RANK, | ||||
| 	[CH_IDLE]      = PRV_NOSV_IDLE, | ||||
| }; | ||||
| 
 | ||||
| static const char *pcf_prefix[CH_MAX] = { | ||||
| @ -130,6 +133,7 @@ static const char *pcf_prefix[CH_MAX] = { | ||||
| 	[CH_APPID]       = "nOS-V task AppID", | ||||
| 	[CH_SUBSYSTEM]   = "nOS-V subsystem", | ||||
| 	[CH_RANK]        = "nOS-V task MPI rank", | ||||
| 	[CH_IDLE]        = "nOS-V idle state", | ||||
| }; | ||||
| 
 | ||||
| static const struct pcf_value_label nosv_ss_values[] = { | ||||
| @ -160,8 +164,16 @@ static const struct pcf_value_label nosv_ss_values[] = { | ||||
| 	{ -1, NULL }, | ||||
| }; | ||||
| 
 | ||||
| static const struct pcf_value_label nosv_worker_idle[] = { | ||||
| 	{ ST_PROGRESSING,   "Progressing" }, | ||||
| 	{ ST_RESTING,       "Resting" }, | ||||
| 	{ ST_ABSORBING,     "Absorbing noise" }, | ||||
| 	{ -1, NULL }, | ||||
| }; | ||||
| 
 | ||||
| static const struct pcf_value_label *pcf_labels[CH_MAX] = { | ||||
| 	[CH_SUBSYSTEM] = nosv_ss_values, | ||||
| 	[CH_IDLE]      = nosv_worker_idle, | ||||
| }; | ||||
| 
 | ||||
| static const long prv_flags[CH_MAX] = { | ||||
| @ -171,6 +183,7 @@ static const long prv_flags[CH_MAX] = { | ||||
| 	[CH_APPID]     = PRV_SKIPDUPNULL, /* Switch to task of same appid */ | ||||
| 	[CH_SUBSYSTEM] = PRV_SKIPDUPNULL, | ||||
| 	[CH_RANK]      = PRV_SKIPDUPNULL, /* Switch to task of same rank */ | ||||
| 	[CH_IDLE]      = PRV_SKIPDUPNULL, | ||||
| }; | ||||
| 
 | ||||
| static const struct model_pvt_spec pvt_spec = { | ||||
| @ -189,6 +202,7 @@ static const int th_track[CH_MAX] = { | ||||
| 	[CH_APPID]     = TRACK_TH_RUN, | ||||
| 	[CH_SUBSYSTEM] = TRACK_TH_ACT, | ||||
| 	[CH_RANK]      = TRACK_TH_RUN, | ||||
| 	[CH_IDLE]      = TRACK_TH_RUN, | ||||
| }; | ||||
| 
 | ||||
| static const int cpu_track[CH_MAX] = { | ||||
| @ -198,6 +212,7 @@ static const int cpu_track[CH_MAX] = { | ||||
| 	[CH_APPID]     = TRACK_TH_RUN, | ||||
| 	[CH_SUBSYSTEM] = TRACK_TH_RUN, | ||||
| 	[CH_RANK]      = TRACK_TH_RUN, | ||||
| 	[CH_IDLE]      = TRACK_TH_RUN, | ||||
| }; | ||||
| 
 | ||||
| /* ----------------- chan_spec ------------------ */ | ||||
| @ -279,6 +294,19 @@ model_nosv_create(struct emu *emu) | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	struct nosv_emu *e = calloc(1, sizeof(struct nosv_emu)); | ||||
| 	if (e == NULL) { | ||||
| 		err("calloc failed:"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	extend_set(&emu->ext, model_id, e); | ||||
| 
 | ||||
| 	if (model_nosv_breakdown_create(emu) != 0) { | ||||
| 		err("model_nosv_breakdown_create failed"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| @ -295,6 +323,28 @@ model_nosv_connect(struct emu *emu) | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	if (emu->args.breakdown && model_nosv_breakdown_connect(emu) != 0) { | ||||
| 		err("model_nosv_breakdown_connect failed"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	for (struct thread *th = emu->system.threads; th; th = th->gnext) { | ||||
| 		struct nosv_thread *mth = EXT(th, model_id); | ||||
| 		struct chan *idle = &mth->m.ch[CH_IDLE]; | ||||
| 		/* By default set all threads as Progressing */ | ||||
| 		if (chan_set(idle, value_int64(ST_PROGRESSING)) != 0) { | ||||
| 			err("chan_push idle failed"); | ||||
| 			return -1; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	for (struct cpu *cpu = emu->system.cpus; cpu; cpu = cpu->next) { | ||||
| 		struct nosv_cpu *mcpu = EXT(cpu, model_id); | ||||
| 		struct mux *mux = &mcpu->m.track[CH_IDLE].mux; | ||||
| 		/* Emit Resting when a CPU has no running threads */ | ||||
| 		mux_set_default(mux, value_int64(ST_RESTING)); | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| @ -343,6 +393,10 @@ finish_pvt(struct emu *emu, const char *name) | ||||
| 	struct pcf *pcf = pvt_get_pcf(pvt); | ||||
| 	long typeid = pvt_type[CH_TYPE]; | ||||
| 	struct pcf_type *pcftype = pcf_find_type(pcf, typeid); | ||||
| 	if (pcftype == NULL) { | ||||
| 		err("cannot find %s pcf type %d", name, typeid); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	for (struct proc *p = sys->procs; p; p = p->gnext) { | ||||
| 		struct nosv_proc *proc = EXT(p, model_id); | ||||
| @ -370,6 +424,11 @@ model_nosv_finish(struct emu *emu) | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	if (model_nosv_breakdown_finish(emu, pcf_labels) != 0) { | ||||
| 		err("model_nosv_breakdown_finish failed"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	/* When running in linter mode perform additional checks */ | ||||
| 	if (emu->args.linter_mode && end_lint(emu) != 0) { | ||||
| 		err("end_lint failed"); | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 David Alvarez
						David Alvarez