Rust wait and sync
This commit is contained in:
@@ -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();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user