Rust wait and sync

This commit is contained in:
ilgeco
2026-08-06 14:32:11 +02:00
parent 10b6ee6c32
commit a963009855
12 changed files with 311 additions and 20 deletions
@@ -326,9 +326,13 @@ fn append_record(
inst_builder.make_inst(recv, inst_data_builder.build());
}
31 => {
inst_data_builder.set_offset_select_value(generic1, generic2);
inst_builder.make_inst(wait, inst_data_builder.build());
}
32 => {
inst_data_builder
.set_imm_core(r2_or_imm + 1)
.set_offset_select_value(generic1, 0);
inst_builder.make_inst(sync, inst_data_builder.build());
}
_ => bail!("unsupported PIM binary opcode {opcode}"),
@@ -601,7 +601,11 @@ fn json_to_wait(
inst_data_builder: &mut InstructionDataBuilder,
json: &Value,
) -> Result<()> {
todo!("Not present in the compiler");
inst_data_builder.set_offset_select_value(
json_i64!(json, "event_register") as i32,
json_i64!(json, "wait_value") as i32,
);
inst_builder.make_inst(wait, inst_data_builder.build());
Ok(())
}
@@ -610,7 +614,10 @@ fn json_to_sync(
inst_data_builder: &mut InstructionDataBuilder,
json: &Value,
) -> Result<()> {
todo!("Not present in the compiler");
inst_data_builder
.set_imm_core(json_i64!(json, "core") as i32 + 1)
.set_offset_select_value(json_i64!(json, "event_register") as i32, 0);
inst_builder.make_inst(sync, inst_data_builder.build());
Ok(())
}
@@ -93,6 +93,8 @@ struct DeadlockInfo {
states: String,
}
type SyncEvents = Vec<[i32; 32]>;
fn print_status(core_instructions: &[CoreInstructions]) {
let mut tot_instructions = 0;
let mut progress = 0;
@@ -135,6 +137,7 @@ impl<'a> Executable<'a> {
} = self;
let mut cpu_progressed = 0;
let max_core = cpu.num_core();
let mut sync_events: SyncEvents = vec![[0; 32]; max_core];
let mut cpu_index = 0;
let mut now = SystemTime::now();
@@ -169,7 +172,9 @@ impl<'a> Executable<'a> {
now = SystemTime::now();
}
}
handle_wait_sync(cpu, cores_instructions, core_result);
if handle_wait_sync(cores_instructions, &mut sync_events, core_result) {
cpu_progressed = 0;
}
match handle_send_recv(cpu, cores_instructions, send_recv, core_result) {
(true, other_cpu_index) => {
cpu_progressed = 0;
@@ -349,12 +354,31 @@ fn detect_deadlock(cores_instructions: &[CoreInstructions]) -> Option<DeadlockIn
None
}
fn handle_wait_sync<'a, 'b, 'c>(
cpu: &'b mut CPU<'a>,
core_instructions: &'c mut [CoreInstructions],
fn handle_wait_sync(
core_instructions: &mut [CoreInstructions],
events: &mut SyncEvents,
core_result: InstructionStatus,
) where
'a: 'b,
'a: 'c,
{
) -> bool {
match core_result {
InstructionStatus::Sync(data) => {
let (source, target) = data.get_core_immcore();
let register = data.offset_select() as usize;
events[target as usize][register] += 1;
core_instructions[source as usize].program_counter += 1;
true
}
InstructionStatus::Waiting(data) => {
let core = data.core_indx() as usize;
let register = data.offset_select() as usize;
let value = data.offset_value();
if events[core][register] >= value {
events[core][register] -= value;
core_instructions[core].program_counter += 1;
true
} else {
false
}
}
_ => false,
}
}
@@ -134,7 +134,7 @@ where
send_recv.sending[sender] = None;
send_recv.receiving[receiver] = None;
}
(transfered, receiver)
(transfered, if transfered { receiver } else { 0 })
}
InstructionStatus::Reciving(instruction_data) => {
let (core_idx, imm_core) = instruction_data.get_core_immcore();
@@ -163,7 +163,7 @@ where
send_recv.sending[sender] = None;
send_recv.receiving[receiver] = None;
}
(transfered, sender)
(transfered, if transfered { sender } else { 0 })
}
_ => (false, 0),
}
@@ -295,3 +295,68 @@ fn multiple_send_recv_test() {
"send_recv failed to store"
);
}
#[test]
fn sync_wait_tokens_test() {
let cpu = common::empty_cpu(2);
let mut cores = CoreInstructionsBuilder::new(2);
let mut instructions = InstructionsBuilder::new();
let mut data = InstructionDataBuilder::new();
data.set_core_indx(1).fix_core_indx();
for _ in 0..2 {
instructions.make_inst(
sync,
data.set_imm_core(2).set_offset_select_value(0, 0).build(),
);
}
cores.set_core(1, instructions.build());
data.set_core_indx(2).fix_core_indx();
for _ in 0..2 {
instructions.make_inst(wait, data.set_offset_select_value(0, 1).build());
}
cores.set_core(2, instructions.build());
Executable::new(cpu, cores.build()).execute().unwrap();
}
#[test]
fn blocked_transfers_do_not_starve_sync_producer() {
let cpu = common::empty_cpu(4);
let mut cores = CoreInstructionsBuilder::new(4);
let mut instructions = InstructionsBuilder::new();
let mut data = InstructionDataBuilder::new();
data.set_core_indx(1).fix_core_indx();
instructions.make_inst(sldi, data.set_rdimm(1, 0).build());
instructions.make_inst(recv, data.set_rd(1).set_imm_core(2).set_imm_len(1).build());
instructions.make_inst(send, data.set_r1(1).set_imm_core(3).set_imm_len(1).build());
cores.set_core(1, instructions.build());
let mut instructions = InstructionsBuilder::new();
let mut data = InstructionDataBuilder::new();
data.set_core_indx(2).fix_core_indx();
instructions.make_inst(sldi, data.set_rdimm(1, 0).build());
instructions.make_inst(wait, data.set_offset_select_value(0, 1).build());
instructions.make_inst(send, data.set_r1(1).set_imm_core(1).set_imm_len(1).build());
cores.set_core(2, instructions.build());
let mut instructions = InstructionsBuilder::new();
let mut data = InstructionDataBuilder::new();
data.set_core_indx(3).fix_core_indx();
instructions.make_inst(sldi, data.set_rdimm(1, 0).build());
instructions.make_inst(recv, data.set_rd(1).set_imm_core(1).set_imm_len(1).build());
cores.set_core(3, instructions.build());
let mut instructions = InstructionsBuilder::new();
let mut data = InstructionDataBuilder::new();
data.set_core_indx(4).fix_core_indx();
instructions.make_inst(
sync,
data.set_imm_core(2).set_offset_select_value(0, 0).build(),
);
cores.set_core(4, instructions.build());
Executable::new(cpu, cores.build()).execute().unwrap();
}