From 176b74ae9233ed6c8724d0456b0085f6a75ec4eb Mon Sep 17 00:00:00 2001 From: Shaokai Lin Date: Fri, 21 Jul 2023 18:20:23 +0200 Subject: [PATCH 1/3] Support ADDI and refactor --- core/threaded/scheduler_static.c | 276 +++++++++--------- core/trace.c | 109 ++++--- .../core/threaded/scheduler_instructions.h | 13 +- include/core/trace.h | 55 ++-- 4 files changed, 233 insertions(+), 220 deletions(-) diff --git a/core/threaded/scheduler_static.c b/core/threaded/scheduler_static.c index 9a6d71fd9..098e74f3e 100644 --- a/core/threaded/scheduler_static.c +++ b/core/threaded/scheduler_static.c @@ -53,7 +53,7 @@ extern instant_t start_time; // Global variables defined in schedule.c: extern const inst_t* static_schedules[]; -extern const long long int hyperperiod; +extern const uint64_t hyperperiod; extern volatile uint32_t hyperperiod_iterations[]; extern volatile uint32_t counters[]; extern const size_t num_counters; @@ -131,6 +131,102 @@ void _lf_sched_wait_for_work( } } +/** + * @brief ADDI: [Lock-free] Add to an integer variable (rs2) by an amount (rs3), + * and store the result in a destination variable (rs1). + * The compiler needs to guarantee a single writer. + * + * @param rs1 + * @param rs2 + * @param pc + * @param returned_reaction + * @param exit_loop + */ +void execute_inst_ADDI(lf_scheduler_t* scheduler, size_t worker_number, uint64_t rs1, uint64_t rs2, uint64_t rs3, size_t* pc, + reaction_t** returned_reaction, bool* exit_loop, volatile uint32_t* iteration) { + tracepoint_static_scheduler_ADDI_starts(scheduler->env->trace, worker_number, (int) *pc); + uint64_t *dst = (uint64_t *) rs1; + uint64_t *src = (uint64_t *) rs2; + *dst = *src + rs3; + *pc += 1; // Increment pc. + tracepoint_static_scheduler_ADDI_ends(scheduler->env->trace, worker_number, (int) *pc); +} + +/** + * @brief ADV: Advance time for a reactor up to a tag (relative to the current hyperperiod). + * + * @param rs1 + * @param rs2 + * @param pc + * @param returned_reaction + * @param exit_loop + */ +void execute_inst_ADV(lf_scheduler_t* scheduler, size_t worker_number, uint64_t rs1, uint64_t rs2, uint64_t rs3, size_t* pc, + reaction_t** returned_reaction, bool* exit_loop, volatile uint32_t* iteration) { + tracepoint_static_scheduler_ADV_starts(scheduler->env->trace, worker_number, (int) *pc); + + // This mutex is quite expensive. + lf_mutex_lock(&(scheduler->env->mutex)); + + self_base_t* reactor = + scheduler->reactor_self_instances[rs1]; + reactor->tag.time = hyperperiod * (*iteration) + rs2; + reactor->tag.microstep = 0; + + // Reset all "is_present" fields of the output ports of the reactor + // Doing this here has the major implicatio that ADV has to execute AFTER + // all downstream reactions have finished. Since it is modifying state that is + // visible to thos reactions. + for (int i = 0; inum_output_ports; i++) { + reactor->output_ports[i]->is_present = false; + } + + if (_lf_is_tag_after_stop_tag(scheduler->env, reactor->tag)) { + scheduler->reactor_reached_stop_tag[rs1] = true; + } + + lf_mutex_unlock(&(scheduler->env->mutex)); + + *pc += 1; // Increment pc. + + tracepoint_static_scheduler_ADV_ends(scheduler->env->trace, worker_number, (int) *pc); +} + +/** + * @brief ADV: Advance time for a reactor up to a tag (relative to the current hyperperiod). + * + * @param rs1 + * @param rs2 + * @param pc + * @param returned_reaction + * @param exit_loop + */ +void execute_inst_ADV2(lf_scheduler_t* scheduler, size_t worker_number, uint64_t rs1, uint64_t rs2, uint64_t rs3, size_t* pc, + reaction_t** returned_reaction, bool* exit_loop, volatile uint32_t* iteration) { + tracepoint_static_scheduler_ADV2_starts(scheduler->env->trace, worker_number, (int) *pc); + + self_base_t* reactor = + scheduler->reactor_self_instances[rs1]; + reactor->tag.time = hyperperiod * (*iteration) + rs2; + reactor->tag.microstep = 0; + + // Reset all "is_present" fields of the output ports of the reactor + // Doing this here has the major implicatio that ADV has to execute AFTER + // all downstream reactions have finished. Since it is modifying state that is + // visible to thos reactions. + for (int i = 0; inum_output_ports; i++) { + reactor->output_ports[i]->is_present = false; + } + + if (_lf_is_tag_after_stop_tag(scheduler->env, reactor->tag)) { + scheduler->reactor_reached_stop_tag[rs1] = true; + } + + *pc += 1; // Increment pc. + + tracepoint_static_scheduler_ADV2_ends(scheduler->env->trace, worker_number, (int) *pc); +} + /** * @brief BIT: Branch If Timeout * Check if timeout is reached. If not, don't do anything. @@ -140,7 +236,7 @@ void _lf_sched_wait_for_work( * FIXME: Use a global variable num_active_reactors instead of iterating over * a for loop. */ -void execute_inst_BIT(lf_scheduler_t* scheduler, size_t worker_number, long long int rs1, long long int rs2, size_t* pc, +void execute_inst_BIT(lf_scheduler_t* scheduler, size_t worker_number, uint64_t rs1, uint64_t rs2, uint64_t rs3, size_t* pc, reaction_t** returned_reaction, bool* exit_loop, volatile uint32_t* iteration) { tracepoint_static_scheduler_BIT_starts(scheduler->env->trace, worker_number, (int) *pc); bool stop = true; @@ -166,7 +262,7 @@ void execute_inst_BIT(lf_scheduler_t* scheduler, size_t worker_number, long long * @param returned_reaction * @param exit_loop */ -void execute_inst_EIT(lf_scheduler_t* scheduler, size_t worker_number, long long int rs1, long long int rs2, size_t* pc, +void execute_inst_EIT(lf_scheduler_t* scheduler, size_t worker_number, uint64_t rs1, uint64_t rs2, uint64_t rs3, size_t* pc, reaction_t** returned_reaction, bool* exit_loop, volatile uint32_t* iteration) { tracepoint_static_scheduler_EIT_starts(scheduler->env->trace, worker_number, (int) *pc); reaction_t* reaction = scheduler->reaction_instances[rs1]; @@ -189,7 +285,7 @@ void execute_inst_EIT(lf_scheduler_t* scheduler, size_t worker_number, long long * @param returned_reaction * @param exit_loop */ -void execute_inst_EXE(lf_scheduler_t* scheduler, size_t worker_number, long long int rs1, long long int rs2, size_t* pc, +void execute_inst_EXE(lf_scheduler_t* scheduler, size_t worker_number, uint64_t rs1, uint64_t rs2, uint64_t rs3, size_t* pc, reaction_t** returned_reaction, bool* exit_loop, volatile uint32_t* iteration) { tracepoint_static_scheduler_EXE_starts(scheduler->env->trace, worker_number, (int) *pc); reaction_t* reaction = scheduler->reaction_instances[rs1]; @@ -209,13 +305,14 @@ void execute_inst_EXE(lf_scheduler_t* scheduler, size_t worker_number, long long * @param returned_reaction * @param exit_loop */ -void execute_inst_DU(lf_scheduler_t* scheduler, size_t worker_number, long long int rs1, long long int rs2, size_t* pc, +void execute_inst_DU(lf_scheduler_t* scheduler, size_t worker_number, uint64_t rs1, uint64_t rs2, uint64_t rs3, size_t* pc, reaction_t** returned_reaction, bool* exit_loop, volatile uint32_t* iteration) { tracepoint_static_scheduler_DU_starts(scheduler->env->trace, worker_number, (int) *pc); // FIXME: There seems to be an overflow problem. // When wakeup_time overflows but lf_time_physical() doesn't, - // _lf_interruptable_sleep_until_locked() terminates immediately. - instant_t wakeup_time = start_time + hyperperiod * (*iteration) + rs1; + // _lf_interruptable_sleep_until_locked() terminates immediately. + uint64_t *src = (uint64_t *)rs1; + instant_t wakeup_time = start_time + *src + rs2; LF_PRINT_DEBUG("start_time: %lld, wakeup_time: %lld, rs1: %lld, iteration: %d, current_physical_time: %lld, hyperperiod: %lld\n", start_time, wakeup_time, rs1, (*iteration), lf_time_physical(), hyperperiod); LF_PRINT_DEBUG("*** Worker %zu delaying", worker_number); _lf_interruptable_sleep_until_locked(scheduler->env, wakeup_time); @@ -233,7 +330,7 @@ void execute_inst_DU(lf_scheduler_t* scheduler, size_t worker_number, long long * @param returned_reaction * @param exit_loop */ -void execute_inst_WU(lf_scheduler_t* scheduler, size_t worker_number, long long int rs1, long long int rs2, size_t* pc, +void execute_inst_WU(lf_scheduler_t* scheduler, size_t worker_number, uint64_t rs1, uint64_t rs2, uint64_t rs3, size_t* pc, reaction_t** returned_reaction, bool* exit_loop, volatile uint32_t* iteration) { tracepoint_static_scheduler_WU_starts(scheduler->env->trace, worker_number, (int) *pc); LF_PRINT_DEBUG("*** Worker %zu waiting", worker_number); @@ -243,81 +340,6 @@ void execute_inst_WU(lf_scheduler_t* scheduler, size_t worker_number, long long tracepoint_static_scheduler_WU_ends(scheduler->env->trace, worker_number, (int) *pc); } -/** - * @brief ADV: Advance time for a reactor up to a tag (relative to the current hyperperiod). - * - * @param rs1 - * @param rs2 - * @param pc - * @param returned_reaction - * @param exit_loop - */ -void execute_inst_ADV(lf_scheduler_t* scheduler, size_t worker_number, long long int rs1, long long int rs2, size_t* pc, - reaction_t** returned_reaction, bool* exit_loop, volatile uint32_t* iteration) { - tracepoint_static_scheduler_ADV_starts(scheduler->env->trace, worker_number, (int) *pc); - - // This mutex is quite expensive. - lf_mutex_lock(&(scheduler->env->mutex)); - - self_base_t* reactor = - scheduler->reactor_self_instances[rs1]; - reactor->tag.time = hyperperiod * (*iteration) + rs2; - reactor->tag.microstep = 0; - - // Reset all "is_present" fields of the output ports of the reactor - // Doing this here has the major implicatio that ADV has to execute AFTER - // all downstream reactions have finished. Since it is modifying state that is - // visible to thos reactions. - for (int i = 0; inum_output_ports; i++) { - reactor->output_ports[i]->is_present = false; - } - - if (_lf_is_tag_after_stop_tag(scheduler->env, reactor->tag)) { - scheduler->reactor_reached_stop_tag[rs1] = true; - } - - lf_mutex_unlock(&(scheduler->env->mutex)); - - *pc += 1; // Increment pc. - - tracepoint_static_scheduler_ADV_ends(scheduler->env->trace, worker_number, (int) *pc); -} - -/** - * @brief ADV: Advance time for a reactor up to a tag (relative to the current hyperperiod). - * - * @param rs1 - * @param rs2 - * @param pc - * @param returned_reaction - * @param exit_loop - */ -void execute_inst_ADV2(lf_scheduler_t* scheduler, size_t worker_number, long long int rs1, long long int rs2, size_t* pc, - reaction_t** returned_reaction, bool* exit_loop, volatile uint32_t* iteration) { - tracepoint_static_scheduler_ADV2_starts(scheduler->env->trace, worker_number, (int) *pc); - - self_base_t* reactor = - scheduler->reactor_self_instances[rs1]; - reactor->tag.time = hyperperiod * (*iteration) + rs2; - reactor->tag.microstep = 0; - - // Reset all "is_present" fields of the output ports of the reactor - // Doing this here has the major implicatio that ADV has to execute AFTER - // all downstream reactions have finished. Since it is modifying state that is - // visible to thos reactions. - for (int i = 0; inum_output_ports; i++) { - reactor->output_ports[i]->is_present = false; - } - - if (_lf_is_tag_after_stop_tag(scheduler->env, reactor->tag)) { - scheduler->reactor_reached_stop_tag[rs1] = true; - } - - *pc += 1; // Increment pc. - - tracepoint_static_scheduler_ADV2_ends(scheduler->env->trace, worker_number, (int) *pc); -} - /** * @brief JMP: Jump to a particular line in the schedule. * @@ -327,7 +349,7 @@ void execute_inst_ADV2(lf_scheduler_t* scheduler, size_t worker_number, long lon * @param returned_reaction * @param exit_loop */ -void execute_inst_JMP(lf_scheduler_t* scheduler, size_t worker_number, long long int rs1, long long int rs2, size_t* pc, +void execute_inst_JMP(lf_scheduler_t* scheduler, size_t worker_number, uint64_t rs1, uint64_t rs2, uint64_t rs3, size_t* pc, reaction_t** returned_reaction, bool* exit_loop, volatile uint32_t* iteration) { tracepoint_static_scheduler_JMP_starts(scheduler->env->trace, worker_number, (int) *pc); if (rs2 != -1) *iteration += 1; @@ -345,12 +367,13 @@ void execute_inst_JMP(lf_scheduler_t* scheduler, size_t worker_number, long long * @param returned_reaction * @param exit_loop */ -void execute_inst_SAC(lf_scheduler_t* scheduler, size_t worker_number, long long int rs1, long long int rs2, size_t* pc, +void execute_inst_SAC(lf_scheduler_t* scheduler, size_t worker_number, uint64_t rs1, uint64_t rs2, uint64_t rs3, size_t* pc, reaction_t** returned_reaction, bool* exit_loop, volatile uint32_t* iteration) { tracepoint_static_scheduler_SAC_starts(scheduler->env->trace, worker_number, (int) *pc); // Compute the next tag for all reactors. - instant_t next_timestamp = hyperperiod * (*iteration) + rs1; + uint64_t *src = (uint64_t *)rs1; + instant_t next_timestamp = *src + rs2; tracepoint_worker_wait_starts(scheduler->env->trace, worker_number); _lf_sched_wait_for_work(scheduler, worker_number, next_timestamp); @@ -360,48 +383,11 @@ void execute_inst_SAC(lf_scheduler_t* scheduler, size_t worker_number, long long tracepoint_static_scheduler_SAC_ends(scheduler->env->trace, worker_number, (int) *pc); } -/** - * @brief INC: INCrement a counter (rs1) by an amount (rs2). - * - * @param rs1 - * @param rs2 - * @param pc - * @param returned_reaction - * @param exit_loop - */ -void execute_inst_INC(lf_scheduler_t* scheduler, size_t worker_number, long long int rs1, long long int rs2, size_t* pc, - reaction_t** returned_reaction, bool* exit_loop, volatile uint32_t* iteration) { - tracepoint_static_scheduler_INC_starts(scheduler->env->trace, worker_number, (int) *pc); - lf_mutex_lock(&(scheduler->env->mutex)); - scheduler->counters[rs1] += rs2; - lf_mutex_unlock(&(scheduler->env->mutex)); - *pc += 1; // Increment pc. - tracepoint_static_scheduler_INC_ends(scheduler->env->trace, worker_number, (int) *pc); -} - -/** - * @brief INC2: [Lock-free] INCrement a counter (rs1) by an amount (rs2). - * The compiler needs to guarantee a single writer. - * - * @param rs1 - * @param rs2 - * @param pc - * @param returned_reaction - * @param exit_loop - */ -void execute_inst_INC2(lf_scheduler_t* scheduler, size_t worker_number, long long int rs1, long long int rs2, size_t* pc, - reaction_t** returned_reaction, bool* exit_loop, volatile uint32_t* iteration) { - tracepoint_static_scheduler_INC2_starts(scheduler->env->trace, worker_number, (int) *pc); - scheduler->counters[rs1] += rs2; - *pc += 1; // Increment pc. - tracepoint_static_scheduler_INC2_ends(scheduler->env->trace, worker_number, (int) *pc); -} - /** * @brief STP: SToP the execution. * */ -void execute_inst_STP(lf_scheduler_t* scheduler, size_t worker_number, long long int rs1, long long int rs2, size_t* pc, +void execute_inst_STP(lf_scheduler_t* scheduler, size_t worker_number, uint64_t rs1, uint64_t rs2, uint64_t rs3, size_t* pc, reaction_t** returned_reaction, bool* exit_loop, volatile uint32_t* iteration) { tracepoint_static_scheduler_STP_starts(scheduler->env->trace, worker_number, (int) *pc); *exit_loop = true; @@ -421,57 +407,53 @@ void execute_inst_STP(lf_scheduler_t* scheduler, size_t worker_number, long long * @param exit_loop a pointer to a boolean indicating whether * the outer while loop should be exited */ -void execute_inst(lf_scheduler_t* scheduler, size_t worker_number, opcode_t op, long long int rs1, long long int rs2, +void execute_inst(lf_scheduler_t* scheduler, size_t worker_number, opcode_t op, uint64_t rs1, uint64_t rs2, uint64_t rs3, size_t* pc, reaction_t** returned_reaction, bool* exit_loop, volatile uint32_t* iteration) { char* op_str = NULL; switch (op) { + case ADDI: + op_str = "ADDI"; + execute_inst_ADDI(scheduler, worker_number, rs1, rs2, rs3, pc, returned_reaction, exit_loop, iteration); + break; case ADV: op_str = "ADV"; - execute_inst_ADV(scheduler, worker_number, rs1, rs2, pc, returned_reaction, exit_loop, iteration); + execute_inst_ADV(scheduler, worker_number, rs1, rs2, rs3, pc, returned_reaction, exit_loop, iteration); break; case ADV2: op_str = "ADV2"; - execute_inst_ADV2(scheduler, worker_number, rs1, rs2, pc, returned_reaction, exit_loop, iteration); + execute_inst_ADV2(scheduler, worker_number, rs1, rs2, rs3, pc, returned_reaction, exit_loop, iteration); break; case BIT: op_str = "BIT"; - execute_inst_BIT(scheduler, worker_number, rs1, rs2, pc, returned_reaction, exit_loop, iteration); + execute_inst_BIT(scheduler, worker_number, rs1, rs2, rs3, pc, returned_reaction, exit_loop, iteration); break; case DU: op_str = "DU"; - execute_inst_DU(scheduler, worker_number, rs1, rs2, pc, returned_reaction, exit_loop, iteration); + execute_inst_DU(scheduler, worker_number, rs1, rs2, rs3, pc, returned_reaction, exit_loop, iteration); break; case EIT: op_str = "EIT"; - execute_inst_EIT(scheduler, worker_number, rs1, rs2, pc, returned_reaction, exit_loop, iteration); + execute_inst_EIT(scheduler, worker_number, rs1, rs2, rs3, pc, returned_reaction, exit_loop, iteration); break; case EXE: op_str = "EXE"; - execute_inst_EXE(scheduler, worker_number, rs1, rs2, pc, returned_reaction, exit_loop, iteration); - break; - case INC: - op_str = "INC"; - execute_inst_INC(scheduler, worker_number, rs1, rs2, pc, returned_reaction, exit_loop, iteration); - break; - case INC2: - op_str = "INC2"; - execute_inst_INC2(scheduler, worker_number, rs1, rs2, pc, returned_reaction, exit_loop, iteration); + execute_inst_EXE(scheduler, worker_number, rs1, rs2, rs3, pc, returned_reaction, exit_loop, iteration); break; case JMP: op_str = "JMP"; - execute_inst_JMP(scheduler, worker_number, rs1, rs2, pc, returned_reaction, exit_loop, iteration); + execute_inst_JMP(scheduler, worker_number, rs1, rs2, rs3, pc, returned_reaction, exit_loop, iteration); break; case SAC: op_str = "SAC"; - execute_inst_SAC(scheduler, worker_number, rs1, rs2, pc, returned_reaction, exit_loop, iteration); + execute_inst_SAC(scheduler, worker_number, rs1, rs2, rs3, pc, returned_reaction, exit_loop, iteration); break; case STP: op_str = "STP"; - execute_inst_STP(scheduler, worker_number, rs1, rs2, pc, returned_reaction, exit_loop, iteration); + execute_inst_STP(scheduler, worker_number, rs1, rs2, rs3, pc, returned_reaction, exit_loop, iteration); break; case WU: op_str = "WU"; - execute_inst_WU(scheduler, worker_number, rs1, rs2, pc, returned_reaction, exit_loop, iteration); + execute_inst_WU(scheduler, worker_number, rs1, rs2, rs3, pc, returned_reaction, exit_loop, iteration); break; default: lf_print_error_and_exit("Invalid instruction: %d", op); @@ -561,17 +543,19 @@ reaction_t* lf_sched_get_ready_reaction(lf_scheduler_t* scheduler, int worker_nu bool exit_loop = false; size_t* pc = &scheduler->pc[worker_number]; opcode_t op; - long long int rs1; - long long int rs2; + uint64_t rs1; + uint64_t rs2; + uint64_t rs3; volatile uint32_t* iteration = &hyperperiod_iterations[worker_number]; while (!exit_loop) { op = current_schedule[*pc].op; rs1 = current_schedule[*pc].rs1; rs2 = current_schedule[*pc].rs2; + rs3 = current_schedule[*pc].rs3; // Execute the current instruction - execute_inst(scheduler, worker_number, op, rs1, rs2, pc, + execute_inst(scheduler, worker_number, op, rs1, rs2, rs3, pc, &returned_reaction, &exit_loop, iteration); LF_PRINT_DEBUG("Worker %d: returned_reaction = %p, exit_loop = %d", diff --git a/core/trace.c b/core/trace.c index ca298ce92..fac833f9a 100644 --- a/core/trace.c +++ b/core/trace.c @@ -457,75 +457,112 @@ void tracepoint_reaction_deadline_missed(trace_t* trace, reaction_t *reaction, i tracepoint(trace, reaction_deadline_missed, reaction->self, NULL, worker, worker, reaction->number, NULL, NULL, 0, false); } +/** Trace the start of the ADDI instruction */ +void tracepoint_static_scheduler_ADDI_starts(trace_t* trace, int worker, int pc) { + tracepoint(trace, static_scheduler_ADDI_starts, NULL, NULL, worker, worker, pc, NULL, NULL, 0, false); +} + +/** Trace the start of the ADV instruction */ void tracepoint_static_scheduler_ADV_starts(trace_t* trace, int worker, int pc) { tracepoint(trace, static_scheduler_ADV_starts, NULL, NULL, worker, worker, pc, NULL, NULL, 0, false); } -void tracepoint_static_scheduler_ADV_ends(trace_t* trace, int worker, int pc) { - tracepoint(trace, static_scheduler_ADV_ends, NULL, NULL, worker, worker, pc, NULL, NULL, 0, false); -} + +/** Trace the start of the ADV2 instruction */ void tracepoint_static_scheduler_ADV2_starts(trace_t* trace, int worker, int pc) { tracepoint(trace, static_scheduler_ADV2_starts, NULL, NULL, worker, worker, pc, NULL, NULL, 0, false); } -void tracepoint_static_scheduler_ADV2_ends(trace_t* trace, int worker, int pc) { - tracepoint(trace, static_scheduler_ADV2_ends, NULL, NULL, worker, worker, pc, NULL, NULL, 0, false); -} + +/** Trace the start of the BIT instruction */ void tracepoint_static_scheduler_BIT_starts(trace_t* trace, int worker, int pc) { tracepoint(trace, static_scheduler_BIT_starts, NULL, NULL, worker, worker, pc, NULL, NULL, 0, false); } -void tracepoint_static_scheduler_BIT_ends(trace_t* trace, int worker, int pc) { - tracepoint(trace, static_scheduler_BIT_ends, NULL, NULL, worker, worker, pc, NULL, NULL, 0, false); -} + +/** Trace the start of the DU instruction */ void tracepoint_static_scheduler_DU_starts(trace_t* trace, int worker, int pc) { tracepoint(trace, static_scheduler_DU_starts, NULL, NULL, worker, worker, pc, NULL, NULL, 0, false); } -void tracepoint_static_scheduler_DU_ends(trace_t* trace, int worker, int pc) { - tracepoint(trace, static_scheduler_DU_ends, NULL, NULL, worker, worker, pc, NULL, NULL, 0, false); -} + +/** Trace the start of the EIT instruction */ void tracepoint_static_scheduler_EIT_starts(trace_t* trace, int worker, int pc) { tracepoint(trace, static_scheduler_EIT_starts, NULL, NULL, worker, worker, pc, NULL, NULL, 0, false); } -void tracepoint_static_scheduler_EIT_ends(trace_t* trace, int worker, int pc) { - tracepoint(trace, static_scheduler_EIT_ends, NULL, NULL, worker, worker, pc, NULL, NULL, 0, false); -} + +/** Trace the start of the EXE instruction */ void tracepoint_static_scheduler_EXE_starts(trace_t* trace, int worker, int pc) { tracepoint(trace, static_scheduler_EXE_starts, NULL, NULL, worker, worker, pc, NULL, NULL, 0, false); } -void tracepoint_static_scheduler_EXE_ends(trace_t* trace, int worker, int pc) { - tracepoint(trace, static_scheduler_EXE_ends, NULL, NULL, worker, worker, pc, NULL, NULL, 0, false); + +/** Trace the start of the JMP instruction */ +void tracepoint_static_scheduler_JMP_starts(trace_t* trace, int worker, int pc) { + tracepoint(trace, static_scheduler_JMP_starts, NULL, NULL, worker, worker, pc, NULL, NULL, 0, false); } -void tracepoint_static_scheduler_INC_starts(trace_t* trace, int worker, int pc) { - tracepoint(trace, static_scheduler_INC_starts, NULL, NULL, worker, worker, pc, NULL, NULL, 0, false); + +/** Trace the start of the SAC instruction */ +void tracepoint_static_scheduler_SAC_starts(trace_t* trace, int worker, int pc) { + tracepoint(trace, static_scheduler_SAC_starts, NULL, NULL, worker, worker, pc, NULL, NULL, 0, false); } -void tracepoint_static_scheduler_INC_ends(trace_t* trace, int worker, int pc) { - tracepoint(trace, static_scheduler_INC_ends, NULL, NULL, worker, worker, pc, NULL, NULL, 0, false); + +/** Trace the start of the STP instruction */ +void tracepoint_static_scheduler_STP_starts(trace_t* trace, int worker, int pc) { + tracepoint(trace, static_scheduler_STP_starts, NULL, NULL, worker, worker, pc, NULL, NULL, 0, false); } -void tracepoint_static_scheduler_INC2_starts(trace_t* trace, int worker, int pc) { - tracepoint(trace, static_scheduler_INC2_starts, NULL, NULL, worker, worker, pc, NULL, NULL, 0, false); + +/** Trace the start of the WU instruction */ +void tracepoint_static_scheduler_WU_starts(trace_t* trace, int worker, int pc) { + tracepoint(trace, static_scheduler_WU_starts, NULL, NULL, worker, worker, pc, NULL, NULL, 0, false); } -void tracepoint_static_scheduler_INC2_ends(trace_t* trace, int worker, int pc) { - tracepoint(trace, static_scheduler_INC2_ends, NULL, NULL, worker, worker, pc, NULL, NULL, 0, false); + +/** Trace the end of the ADDI instruction */ +void tracepoint_static_scheduler_ADDI_ends(trace_t* trace, int worker, int pc) { + tracepoint(trace, static_scheduler_ADDI_ends, NULL, NULL, worker, worker, pc, NULL, NULL, 0, false); } -void tracepoint_static_scheduler_JMP_starts(trace_t* trace, int worker, int pc) { - tracepoint(trace, static_scheduler_JMP_starts, NULL, NULL, worker, worker, pc, NULL, NULL, 0, false); + +/** Trace the end of the ADV instruction */ +void tracepoint_static_scheduler_ADV_ends(trace_t* trace, int worker, int pc) { + tracepoint(trace, static_scheduler_ADV_ends, NULL, NULL, worker, worker, pc, NULL, NULL, 0, false); +} + +/** Trace the end of the ADV2 instruction */ +void tracepoint_static_scheduler_ADV2_ends(trace_t* trace, int worker, int pc) { + tracepoint(trace, static_scheduler_ADV2_ends, NULL, NULL, worker, worker, pc, NULL, NULL, 0, false); } + +/** Trace the end of the BIT instruction */ +void tracepoint_static_scheduler_BIT_ends(trace_t* trace, int worker, int pc) { + tracepoint(trace, static_scheduler_BIT_ends, NULL, NULL, worker, worker, pc, NULL, NULL, 0, false); +} + +/** Trace the end of the DU instruction */ +void tracepoint_static_scheduler_DU_ends(trace_t* trace, int worker, int pc) { + tracepoint(trace, static_scheduler_DU_ends, NULL, NULL, worker, worker, pc, NULL, NULL, 0, false); +} + +/** Trace the end of the EIT instruction */ +void tracepoint_static_scheduler_EIT_ends(trace_t* trace, int worker, int pc) { + tracepoint(trace, static_scheduler_EIT_ends, NULL, NULL, worker, worker, pc, NULL, NULL, 0, false); +} + +/** Trace the end of the EXE instruction */ +void tracepoint_static_scheduler_EXE_ends(trace_t* trace, int worker, int pc) { + tracepoint(trace, static_scheduler_EXE_ends, NULL, NULL, worker, worker, pc, NULL, NULL, 0, false); +} + +/** Trace the end of the JMP instruction */ void tracepoint_static_scheduler_JMP_ends(trace_t* trace, int worker, int pc) { tracepoint(trace, static_scheduler_JMP_ends, NULL, NULL, worker, worker, pc, NULL, NULL, 0, false); } -void tracepoint_static_scheduler_SAC_starts(trace_t* trace, int worker, int pc) { - tracepoint(trace, static_scheduler_SAC_starts, NULL, NULL, worker, worker, pc, NULL, NULL, 0, false); -} + +/** Trace the end of the SAC instruction */ void tracepoint_static_scheduler_SAC_ends(trace_t* trace, int worker, int pc) { tracepoint(trace, static_scheduler_SAC_ends, NULL, NULL, worker, worker, pc, NULL, NULL, 0, false); } -void tracepoint_static_scheduler_STP_starts(trace_t* trace, int worker, int pc) { - tracepoint(trace, static_scheduler_STP_starts, NULL, NULL, worker, worker, pc, NULL, NULL, 0, false); -} + +/** Trace the end of the STP instruction */ void tracepoint_static_scheduler_STP_ends(trace_t* trace, int worker, int pc) { tracepoint(trace, static_scheduler_STP_ends, NULL, NULL, worker, worker, pc, NULL, NULL, 0, false); } -void tracepoint_static_scheduler_WU_starts(trace_t* trace, int worker, int pc) { - tracepoint(trace, static_scheduler_WU_starts, NULL, NULL, worker, worker, pc, NULL, NULL, 0, false); -} + +/** Trace the end of the WU instruction */ void tracepoint_static_scheduler_WU_ends(trace_t* trace, int worker, int pc) { tracepoint(trace, static_scheduler_WU_ends, NULL, NULL, worker, worker, pc, NULL, NULL, 0, false); } diff --git a/include/core/threaded/scheduler_instructions.h b/include/core/threaded/scheduler_instructions.h index e9deb431d..1f981d0f6 100644 --- a/include/core/threaded/scheduler_instructions.h +++ b/include/core/threaded/scheduler_instructions.h @@ -3,28 +3,26 @@ * @brief Format of the instruction set * * VM Instruction Set + * - ADDI rs1, rs2, rs3 : [Lock-free] Add to an integer variable (rs2) by an amount (rs3), and store the result in a destination variable (rs1). * - ADV rs1, rs2 : ADVance the logical time of a reactor (rs1) by a specified amount (rs2). Add a delay_until here. * - ADV2 rs1, rs2 : Lock-free version of ADV. The compiler needs to guarantee only a single thread can update a reactor's tag. * - BIT rs1, : (Branch-If-Timeout) Branch to a location (rs1) if all reactors reach timeout. * - DU rs1, rs2 : Delay Until a physical time offset (rs1) wrt the current hyperperiod is reached. * - EIT rs1 : Execute a reaction (rs1) If Triggered. FIXME: Combine with a branch. * - EXE rs1 : EXEcute a reaction (rs1) (used for known triggers such as startup, shutdown, and timers). - * - INC rs1, rs2 : INCrement a counter (rs1) by an amount (rs2). - * - INC2 rs1, rs2 : Lock-free version of INC. The compiler needs to guarantee single writer. * - JMP rs1 : JuMP to a location (rs1). * - SAC : (Sync-Advance-Clear) synchronize all workers until all execute SAC and let the last idle worker reset all counters to 0. * - STP : SToP the execution. * - WU rs1, rs2 : Wait Until a counting variable (rs1) to reach a desired value (rs2). */ typedef enum { + ADDI, ADV, ADV2, BIT, DU, EIT, EXE, - INC, - INC2, JMP, SAC, STP, @@ -32,7 +30,8 @@ typedef enum { } opcode_t; typedef struct inst_t { - opcode_t op; - long long int rs1; - long long int rs2; + opcode_t op; + uint64_t rs1; + uint64_t rs2; + uint64_t rs3; } inst_t; \ No newline at end of file diff --git a/include/core/trace.h b/include/core/trace.h index 58125731f..62de1b746 100644 --- a/include/core/trace.h +++ b/include/core/trace.h @@ -77,26 +77,24 @@ typedef enum scheduler_advancing_time_starts, scheduler_advancing_time_ends, // Static scheduler instructions + static_scheduler_ADDI_starts, static_scheduler_ADV_starts, static_scheduler_ADV2_starts, static_scheduler_BIT_starts, static_scheduler_DU_starts, static_scheduler_EIT_starts, static_scheduler_EXE_starts, - static_scheduler_INC_starts, - static_scheduler_INC2_starts, static_scheduler_JMP_starts, static_scheduler_SAC_starts, static_scheduler_STP_starts, static_scheduler_WU_starts, + static_scheduler_ADDI_ends, static_scheduler_ADV_ends, static_scheduler_ADV2_ends, static_scheduler_BIT_ends, static_scheduler_DU_ends, static_scheduler_EIT_ends, static_scheduler_EXE_ends, - static_scheduler_INC_ends, - static_scheduler_INC2_ends, static_scheduler_JMP_ends, static_scheduler_SAC_ends, static_scheduler_STP_ends, @@ -480,32 +478,29 @@ void tracepoint_scheduler_advancing_time_ends(trace_t* trace); */ void tracepoint_reaction_deadline_missed(trace_t* trace, reaction_t *reaction, int worker); +void tracepoint_static_scheduler_ADDI_starts(trace_t* trace, int worker, int pc); void tracepoint_static_scheduler_ADV_starts(trace_t* trace, int worker, int pc); -void tracepoint_static_scheduler_ADV_ends(trace_t* trace, int worker, int pc); void tracepoint_static_scheduler_ADV2_starts(trace_t* trace, int worker, int pc); -void tracepoint_static_scheduler_ADV2_ends(trace_t* trace, int worker, int pc); void tracepoint_static_scheduler_BIT_starts(trace_t* trace, int worker, int pc); -void tracepoint_static_scheduler_BIT_ends(trace_t* trace, int worker, int pc); void tracepoint_static_scheduler_DU_starts(trace_t* trace, int worker, int pc); -void tracepoint_static_scheduler_DU_ends(trace_t* trace, int worker, int pc); void tracepoint_static_scheduler_EIT_starts(trace_t* trace, int worker, int pc); -void tracepoint_static_scheduler_EIT_ends(trace_t* trace, int worker, int pc); void tracepoint_static_scheduler_EXE_starts(trace_t* trace, int worker, int pc); -void tracepoint_static_scheduler_EXE_ends(trace_t* trace, int worker, int pc); -void tracepoint_static_scheduler_INC_starts(trace_t* trace, int worker, int pc); -void tracepoint_static_scheduler_INC_ends(trace_t* trace, int worker, int pc); -void tracepoint_static_scheduler_INC2_starts(trace_t* trace, int worker, int pc); -void tracepoint_static_scheduler_INC2_ends(trace_t* trace, int worker, int pc); void tracepoint_static_scheduler_JMP_starts(trace_t* trace, int worker, int pc); -void tracepoint_static_scheduler_JMP_ends(trace_t* trace, int worker, int pc); void tracepoint_static_scheduler_SAC_starts(trace_t* trace, int worker, int pc); -void tracepoint_static_scheduler_SAC_ends(trace_t* trace, int worker, int pc); void tracepoint_static_scheduler_STP_starts(trace_t* trace, int worker, int pc); -void tracepoint_static_scheduler_STP_ends(trace_t* trace, int worker, int pc); void tracepoint_static_scheduler_WU_starts(trace_t* trace, int worker, int pc); +void tracepoint_static_scheduler_ADDI_ends(trace_t* trace, int worker, int pc); +void tracepoint_static_scheduler_ADV_ends(trace_t* trace, int worker, int pc); +void tracepoint_static_scheduler_ADV2_ends(trace_t* trace, int worker, int pc); +void tracepoint_static_scheduler_BIT_ends(trace_t* trace, int worker, int pc); +void tracepoint_static_scheduler_DU_ends(trace_t* trace, int worker, int pc); +void tracepoint_static_scheduler_EIT_ends(trace_t* trace, int worker, int pc); +void tracepoint_static_scheduler_EXE_ends(trace_t* trace, int worker, int pc); +void tracepoint_static_scheduler_JMP_ends(trace_t* trace, int worker, int pc); +void tracepoint_static_scheduler_SAC_ends(trace_t* trace, int worker, int pc); +void tracepoint_static_scheduler_STP_ends(trace_t* trace, int worker, int pc); void tracepoint_static_scheduler_WU_ends(trace_t* trace, int worker, int pc); - /** * Flush any buffered trace records to the trace file and * close the files. @@ -598,29 +593,27 @@ void tracepoint_rti_from_federate(trace_t* trace, trace_event_t event_type, int #define tracepoint_scheduler_advancing_time_starts(...); #define tracepoint_scheduler_advancing_time_ends(...); #define tracepoint_reaction_deadline_missed(...); +#define tracepoint_static_scheduler_ADDI_starts(...); #define tracepoint_static_scheduler_ADV_starts(...); -#define tracepoint_static_scheduler_ADV_ends(...); #define tracepoint_static_scheduler_ADV2_starts(...); -#define tracepoint_static_scheduler_ADV2_ends(...); #define tracepoint_static_scheduler_BIT_starts(...); -#define tracepoint_static_scheduler_BIT_ends(...); #define tracepoint_static_scheduler_DU_starts(...); -#define tracepoint_static_scheduler_DU_ends(...); #define tracepoint_static_scheduler_EIT_starts(...); -#define tracepoint_static_scheduler_EIT_ends(...); #define tracepoint_static_scheduler_EXE_starts(...); -#define tracepoint_static_scheduler_EXE_ends(...); -#define tracepoint_static_scheduler_INC_starts(...); -#define tracepoint_static_scheduler_INC_ends(...); -#define tracepoint_static_scheduler_INC2_starts(...); -#define tracepoint_static_scheduler_INC2_ends(...); #define tracepoint_static_scheduler_JMP_starts(...); -#define tracepoint_static_scheduler_JMP_ends(...); #define tracepoint_static_scheduler_SAC_starts(...); -#define tracepoint_static_scheduler_SAC_ends(...); #define tracepoint_static_scheduler_STP_starts(...); -#define tracepoint_static_scheduler_STP_ends(...); #define tracepoint_static_scheduler_WU_starts(...); +#define tracepoint_static_scheduler_ADDI_ends(...); +#define tracepoint_static_scheduler_ADV_ends(...); +#define tracepoint_static_scheduler_ADV2_ends(...); +#define tracepoint_static_scheduler_BIT_ends(...); +#define tracepoint_static_scheduler_DU_ends(...); +#define tracepoint_static_scheduler_EIT_ends(...); +#define tracepoint_static_scheduler_EXE_ends(...); +#define tracepoint_static_scheduler_JMP_ends(...); +#define tracepoint_static_scheduler_SAC_ends(...); +#define tracepoint_static_scheduler_STP_ends(...); #define tracepoint_static_scheduler_WU_ends(...); #define tracepoint_federate_to_rti(...); #define tracepoint_federate_from_rti(...); From f2cc4817278bf34cf638c0326eb774ce27c43f8e Mon Sep 17 00:00:00 2001 From: Shaokai Lin Date: Fri, 21 Jul 2023 18:30:39 +0200 Subject: [PATCH 2/3] Update ADV and ADV2 --- core/threaded/scheduler_static.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/core/threaded/scheduler_static.c b/core/threaded/scheduler_static.c index 098e74f3e..2ac28eec7 100644 --- a/core/threaded/scheduler_static.c +++ b/core/threaded/scheduler_static.c @@ -168,9 +168,10 @@ void execute_inst_ADV(lf_scheduler_t* scheduler, size_t worker_number, uint64_t // This mutex is quite expensive. lf_mutex_lock(&(scheduler->env->mutex)); + uint64_t *src = (uint64_t *)rs2; self_base_t* reactor = scheduler->reactor_self_instances[rs1]; - reactor->tag.time = hyperperiod * (*iteration) + rs2; + reactor->tag.time = *src + rs3; reactor->tag.microstep = 0; // Reset all "is_present" fields of the output ports of the reactor @@ -205,9 +206,10 @@ void execute_inst_ADV2(lf_scheduler_t* scheduler, size_t worker_number, uint64_t reaction_t** returned_reaction, bool* exit_loop, volatile uint32_t* iteration) { tracepoint_static_scheduler_ADV2_starts(scheduler->env->trace, worker_number, (int) *pc); + uint64_t *src = (uint64_t *)rs2; self_base_t* reactor = scheduler->reactor_self_instances[rs1]; - reactor->tag.time = hyperperiod * (*iteration) + rs2; + reactor->tag.time = *src + rs3; reactor->tag.microstep = 0; // Reset all "is_present" fields of the output ports of the reactor From 321e17c8e103b6de1ffac6aa246063361f665b18 Mon Sep 17 00:00:00 2001 From: Shaokai Lin Date: Mon, 24 Jul 2023 14:24:49 +0200 Subject: [PATCH 3/3] Update comments --- core/threaded/scheduler_static.c | 85 +++---------------- .../core/threaded/scheduler_instructions.h | 6 +- 2 files changed, 14 insertions(+), 77 deletions(-) diff --git a/core/threaded/scheduler_static.c b/core/threaded/scheduler_static.c index 2ac28eec7..2b9c0de34 100644 --- a/core/threaded/scheduler_static.c +++ b/core/threaded/scheduler_static.c @@ -132,15 +132,7 @@ void _lf_sched_wait_for_work( } /** - * @brief ADDI: [Lock-free] Add to an integer variable (rs2) by an amount (rs3), - * and store the result in a destination variable (rs1). - * The compiler needs to guarantee a single writer. - * - * @param rs1 - * @param rs2 - * @param pc - * @param returned_reaction - * @param exit_loop + * @brief The implementation of the ADDI instruction */ void execute_inst_ADDI(lf_scheduler_t* scheduler, size_t worker_number, uint64_t rs1, uint64_t rs2, uint64_t rs3, size_t* pc, reaction_t** returned_reaction, bool* exit_loop, volatile uint32_t* iteration) { @@ -153,13 +145,7 @@ void execute_inst_ADDI(lf_scheduler_t* scheduler, size_t worker_number, uint64_t } /** - * @brief ADV: Advance time for a reactor up to a tag (relative to the current hyperperiod). - * - * @param rs1 - * @param rs2 - * @param pc - * @param returned_reaction - * @param exit_loop + * @brief The implementation of the ADV instruction */ void execute_inst_ADV(lf_scheduler_t* scheduler, size_t worker_number, uint64_t rs1, uint64_t rs2, uint64_t rs3, size_t* pc, reaction_t** returned_reaction, bool* exit_loop, volatile uint32_t* iteration) { @@ -194,13 +180,7 @@ void execute_inst_ADV(lf_scheduler_t* scheduler, size_t worker_number, uint64_t } /** - * @brief ADV: Advance time for a reactor up to a tag (relative to the current hyperperiod). - * - * @param rs1 - * @param rs2 - * @param pc - * @param returned_reaction - * @param exit_loop + * @brief The implementation of the ADV2 instruction */ void execute_inst_ADV2(lf_scheduler_t* scheduler, size_t worker_number, uint64_t rs1, uint64_t rs2, uint64_t rs3, size_t* pc, reaction_t** returned_reaction, bool* exit_loop, volatile uint32_t* iteration) { @@ -230,9 +210,7 @@ void execute_inst_ADV2(lf_scheduler_t* scheduler, size_t worker_number, uint64_t } /** - * @brief BIT: Branch If Timeout - * Check if timeout is reached. If not, don't do anything. - * If so, jump to a specified location (rs1). + * @brief The implementation of the BIT instruction * * FIXME: Should the timeout value be an operand? * FIXME: Use a global variable num_active_reactors instead of iterating over @@ -254,15 +232,7 @@ void execute_inst_BIT(lf_scheduler_t* scheduler, size_t worker_number, uint64_t } /** - * @brief EIT: "Execute-If-Triggered" - * Check if the reaction status is "queued." - * If so, return the reaction pointer and advance pc. - * - * @param rs1 - * @param rs2 - * @param pc - * @param returned_reaction - * @param exit_loop + * @brief The implementation of the EIT instruction */ void execute_inst_EIT(lf_scheduler_t* scheduler, size_t worker_number, uint64_t rs1, uint64_t rs2, uint64_t rs3, size_t* pc, reaction_t** returned_reaction, bool* exit_loop, volatile uint32_t* iteration) { @@ -279,13 +249,7 @@ void execute_inst_EIT(lf_scheduler_t* scheduler, size_t worker_number, uint64_t } /** - * @brief EXE: Execute a reaction - * - * @param rs1 - * @param rs2 - * @param pc - * @param returned_reaction - * @param exit_loop + * @brief The implementation of the EXE instruction */ void execute_inst_EXE(lf_scheduler_t* scheduler, size_t worker_number, uint64_t rs1, uint64_t rs2, uint64_t rs3, size_t* pc, reaction_t** returned_reaction, bool* exit_loop, volatile uint32_t* iteration) { @@ -298,14 +262,7 @@ void execute_inst_EXE(lf_scheduler_t* scheduler, size_t worker_number, uint64_t } /** - * @brief DU: Delay Until a physical time offset (rs1) wrt the current hyperperiod is reached. - * - * @param worker_number - * @param rs1 - * @param rs2 - * @param pc - * @param returned_reaction - * @param exit_loop + * @brief The implementation of the DU instruction */ void execute_inst_DU(lf_scheduler_t* scheduler, size_t worker_number, uint64_t rs1, uint64_t rs2, uint64_t rs3, size_t* pc, reaction_t** returned_reaction, bool* exit_loop, volatile uint32_t* iteration) { @@ -324,13 +281,7 @@ void execute_inst_DU(lf_scheduler_t* scheduler, size_t worker_number, uint64_t r } /** - * @brief WU: Wait until a counting variable reaches a specified value. - * - * @param rs1 - * @param rs2 - * @param pc - * @param returned_reaction - * @param exit_loop + * @brief The implementation of the WU instruction */ void execute_inst_WU(lf_scheduler_t* scheduler, size_t worker_number, uint64_t rs1, uint64_t rs2, uint64_t rs3, size_t* pc, reaction_t** returned_reaction, bool* exit_loop, volatile uint32_t* iteration) { @@ -343,13 +294,7 @@ void execute_inst_WU(lf_scheduler_t* scheduler, size_t worker_number, uint64_t r } /** - * @brief JMP: Jump to a particular line in the schedule. - * - * @param rs1 - * @param rs2 - * @param pc - * @param returned_reaction - * @param exit_loop + * @brief The implementation of the JMP instruction */ void execute_inst_JMP(lf_scheduler_t* scheduler, size_t worker_number, uint64_t rs1, uint64_t rs2, uint64_t rs3, size_t* pc, reaction_t** returned_reaction, bool* exit_loop, volatile uint32_t* iteration) { @@ -360,14 +305,7 @@ void execute_inst_JMP(lf_scheduler_t* scheduler, size_t worker_number, uint64_t } /** - * @brief SAC: (Sync-Advance-Clear) synchronize all workers until all execute SAC - * and let the last idle worker reset all counters to 0. - * - * @param rs1 - * @param rs2 - * @param pc - * @param returned_reaction - * @param exit_loop + * @brief The implementation of the SAC instruction */ void execute_inst_SAC(lf_scheduler_t* scheduler, size_t worker_number, uint64_t rs1, uint64_t rs2, uint64_t rs3, size_t* pc, reaction_t** returned_reaction, bool* exit_loop, volatile uint32_t* iteration) { @@ -386,8 +324,7 @@ void execute_inst_SAC(lf_scheduler_t* scheduler, size_t worker_number, uint64_t } /** - * @brief STP: SToP the execution. - * + * @brief The implementation of the STP instruction */ void execute_inst_STP(lf_scheduler_t* scheduler, size_t worker_number, uint64_t rs1, uint64_t rs2, uint64_t rs3, size_t* pc, reaction_t** returned_reaction, bool* exit_loop, volatile uint32_t* iteration) { diff --git a/include/core/threaded/scheduler_instructions.h b/include/core/threaded/scheduler_instructions.h index 1f981d0f6..f5a7b1112 100644 --- a/include/core/threaded/scheduler_instructions.h +++ b/include/core/threaded/scheduler_instructions.h @@ -4,14 +4,14 @@ * * VM Instruction Set * - ADDI rs1, rs2, rs3 : [Lock-free] Add to an integer variable (rs2) by an amount (rs3), and store the result in a destination variable (rs1). - * - ADV rs1, rs2 : ADVance the logical time of a reactor (rs1) by a specified amount (rs2). Add a delay_until here. + * - ADV rs1, rs2 : ADVance the logical time of a reactor (rs1) based on a variable offset (rs2) plus a fixed time duration (rs3). * - ADV2 rs1, rs2 : Lock-free version of ADV. The compiler needs to guarantee only a single thread can update a reactor's tag. * - BIT rs1, : (Branch-If-Timeout) Branch to a location (rs1) if all reactors reach timeout. - * - DU rs1, rs2 : Delay Until a physical time offset (rs1) wrt the current hyperperiod is reached. + * - DU rs1, rs2 : Delay Until the physical time reaches a variable offset (rs1) plus a fixed time duration (rs2). * - EIT rs1 : Execute a reaction (rs1) If Triggered. FIXME: Combine with a branch. * - EXE rs1 : EXEcute a reaction (rs1) (used for known triggers such as startup, shutdown, and timers). * - JMP rs1 : JuMP to a location (rs1). - * - SAC : (Sync-Advance-Clear) synchronize all workers until all execute SAC and let the last idle worker reset all counters to 0. + * - SAC : (Sync-Advance-Clear) synchronize all workers until all execute SAC, let the last idle worker reset all counters to 0, and advance all reactors' logical time to a variable offset (rs1) plus a fixed time duration (rs2). * - STP : SToP the execution. * - WU rs1, rs2 : Wait Until a counting variable (rs1) to reach a desired value (rs2). */