Files
Raptor/backend-simulators/pim/pim-simulator/tests/simd.rs
2026-02-23 16:17:52 +01:00

1059 lines
29 KiB
Rust

use pimcore::{
Executable,
cpu::CPU,
instruction_set::{InstructionsBuilder, instruction_data::InstructionDataBuilder, isa::*},
memory_manager::{MemoryStorable, type_traits::UpcastDestTraits},
};
/// VVADD Test
fn vvadd_test_generic<F, T>(err: &str)
where
F: From<f32> + std::fmt::Debug + PartialEq<F> + MemoryStorable,
T: From<f32> + std::fmt::Debug + PartialEq<T> + MemoryStorable,
{
let mut cpu = CPU::new(0);
let buff: [F; _] = [
1.0.into(),
2.0.into(),
3.0.into(),
4.0.into(),
5.0.into(),
6.0.into(),
7.0.into(),
8.0.into(),
9.0.into(),
10.0.into(),
11.0.into(),
12.0.into(),
13.0.into(),
14.0.into(),
15.0.into(),
16.0.into(),
];
cpu.host().execute_store(0, &buff).unwrap();
let mut inst_builder = InstructionsBuilder::new();
let mut idata_build = InstructionDataBuilder::new();
idata_build.set_core_indx(0).fix_core_indx();
inst_builder.make_inst(sldi, idata_build.set_rdimm(1, 0).build());
inst_builder.make_inst(
sldi,
idata_build.set_rdimm(2, 8 * size_of::<F>() as i32).build(),
);
inst_builder.make_inst(
sldi,
idata_build.set_rdimm(3, 16 * size_of::<F>() as i32).build(),
);
inst_builder.make_inst(
setbw,
idata_build
.set_ibiw_obiw(8 * size_of::<F>() as i32, 8 * size_of::<T>() as i32)
.build(),
);
inst_builder.make_inst(
vvadd,
idata_build
.set_rdr1r2(3, 1, 2)
.set_imm_len(8 * size_of::<F>() as i32)
.build(),
);
let core_instruction = vec![inst_builder.build().into()];
let mut executable = Executable::new(cpu, core_instruction);
executable.execute();
// Check result correct
assert_eq!(
executable
.cpu_mut()
.host()
.load::<T>(16 * size_of::<F>(), 8 * size_of::<T>()).unwrap()[0],
vec![
10.0.into(),
12.0.into(),
14.0.into(),
16.0.into(),
18.0.into(),
20.0.into(),
22.0.into(),
24.0.into()
],
"Wrong result for {}",
err
);
// Check first part equal
assert_eq!(
executable
.cpu_mut()
.host()
.load::<F>(0, 16 * size_of::<F>()).unwrap()[0],
&buff,
"Altered first part for {}",
err
);
//Check that later is 0
assert_eq!(
executable.cpu_mut().host().load::<i32>(
16 * size_of::<F>() + 8 * size_of::<T>(),
4 * size_of::<i32>()
).unwrap()[0],
[0, 0, 0, 0],
"Altered first part for {}",
err
);
}
#[test]
fn vvadd_test() {
vvadd_test_generic::<f32, f32>("vvadd<f32,f32>");
vvadd_test_generic::<f64, f32>("vvadd<f64,f32>");
vvadd_test_generic::<f32, f64>("vvadd<f32,f64>");
vvadd_test_generic::<f64, f64>("vvadd<f64,f64>");
}
/// VVSUM Test
fn vvsub_test_generic<F, T>(err: &str)
where
F: From<f32> + std::fmt::Debug + PartialEq<F> + MemoryStorable,
T: From<f32> + std::fmt::Debug + PartialEq<T> + MemoryStorable,
{
let mut cpu = CPU::new(0);
let buff: [F; _] = [
1.0.into(),
2.0.into(),
3.0.into(),
4.0.into(),
5.0.into(),
6.0.into(),
7.0.into(),
8.0.into(),
9.0.into(),
10.0.into(),
11.0.into(),
12.0.into(),
13.0.into(),
14.0.into(),
15.0.into(),
16.0.into(),
];
cpu.host().execute_store(0, &buff).unwrap();
let mut inst_builder = InstructionsBuilder::new();
let mut idata_build = InstructionDataBuilder::new();
idata_build.set_core_indx(0).fix_core_indx();
inst_builder.make_inst(sldi, idata_build.set_rdimm(1, 0).build());
inst_builder.make_inst(
sldi,
idata_build.set_rdimm(2, 8 * size_of::<F>() as i32).build(),
);
inst_builder.make_inst(
sldi,
idata_build.set_rdimm(3, 16 * size_of::<F>() as i32).build(),
);
inst_builder.make_inst(
setbw,
idata_build
.set_ibiw_obiw(8 * size_of::<F>() as i32, 8 * size_of::<T>() as i32)
.build(),
);
inst_builder.make_inst(
vvsub,
idata_build
.set_rdr1r2(3, 1, 2)
.set_imm_len(8 * size_of::<F>() as i32)
.build(),
);
let core_instruction = vec![inst_builder.build().into()];
let mut executable = Executable::new(cpu, core_instruction);
executable.execute();
// Check result correct
assert_eq!(
executable
.cpu_mut()
.host()
.load::<T>(16 * size_of::<F>(), 8 * size_of::<T>()).unwrap()[0],
vec![
(-8.0).into(),
(-8.0).into(),
(-8.0).into(),
(-8.0).into(),
(-8.0).into(),
(-8.0).into(),
(-8.0).into(),
(-8.0).into()
],
"Wrong result for {}",
err
);
// Check first part equal
assert_eq!(
executable
.cpu_mut()
.host()
.load::<F>(0, 16 * size_of::<F>()).unwrap()[0],
&buff,
"Altered first part for {}",
err
);
//Check that later is 0
assert_eq!(
executable.cpu_mut().host().load::<i32>(
16 * size_of::<F>() + 8 * size_of::<T>(),
4 * size_of::<i32>()
).unwrap()[0],
[0, 0, 0, 0],
"Altered first part for {}",
err
);
}
#[test]
fn vvsub_test() {
vvsub_test_generic::<f32, f32>("vvsub<f32,f32>");
vvsub_test_generic::<f64, f32>("vvsub<f64,f32>");
vvsub_test_generic::<f32, f64>("vvsub<f32,f64>");
vvsub_test_generic::<f64, f64>("vvsub<f64,f64>");
}
/// VVMUL Test
fn vvmul_test_generic<F, T>(err: &str)
where
F: From<f32> + std::fmt::Debug + PartialEq<F> + MemoryStorable,
T: From<f32> + std::fmt::Debug + PartialEq<T> + MemoryStorable,
{
let mut cpu = CPU::new(0);
let buff: [F; _] = [
1.0.into(),
2.0.into(),
3.0.into(),
4.0.into(),
5.0.into(),
6.0.into(),
7.0.into(),
8.0.into(),
9.0.into(),
10.0.into(),
11.0.into(),
12.0.into(),
13.0.into(),
14.0.into(),
15.0.into(),
16.0.into(),
];
cpu.host().execute_store(0, &buff).unwrap();
let mut inst_builder = InstructionsBuilder::new();
let mut idata_build = InstructionDataBuilder::new();
idata_build.set_core_indx(0).fix_core_indx();
inst_builder.make_inst(sldi, idata_build.set_rdimm(1, 0).build());
inst_builder.make_inst(
sldi,
idata_build.set_rdimm(2, 8 * size_of::<F>() as i32).build(),
);
inst_builder.make_inst(
sldi,
idata_build.set_rdimm(3, 16 * size_of::<F>() as i32).build(),
);
inst_builder.make_inst(
setbw,
idata_build
.set_ibiw_obiw(8 * size_of::<F>() as i32, 8 * size_of::<T>() as i32)
.build(),
);
inst_builder.make_inst(
vvmul,
idata_build
.set_rdr1r2(3, 1, 2)
.set_imm_len(8 * size_of::<F>() as i32)
.build(),
);
let core_instruction = vec![inst_builder.build().into()];
let mut executable = Executable::new(cpu, core_instruction);
executable.execute();
// Check result correct
assert_eq!(
executable
.cpu_mut()
.host()
.load::<T>(16 * size_of::<F>(), 8 * size_of::<T>()).unwrap()[0],
vec![
(9.0).into(),
(20.0).into(),
(33.0).into(),
(48.0).into(),
(65.0).into(),
(84.0).into(),
(105.0).into(),
(128.0).into()
],
"Wrong result for {}",
err
);
// Check first part equal
assert_eq!(
executable
.cpu_mut()
.host()
.load::<F>(0, 16 * size_of::<F>()).unwrap()[0],
&buff,
"Altered first part for {}",
err
);
//Check that later is 0
assert_eq!(
executable.cpu_mut().host().load::<i32>(
16 * size_of::<F>() + 8 * size_of::<T>(),
4 * size_of::<i32>()
).unwrap()[0],
[0, 0, 0, 0],
"Altered first part for {}",
err
);
}
#[test]
fn vvmul_test() {
vvmul_test_generic::<f32, f32>("vvmul<f32,f32>");
vvmul_test_generic::<f64, f32>("vvmul<f64,f32>");
vvmul_test_generic::<f32, f64>("vvmul<f32,f64>");
vvmul_test_generic::<f64, f64>("vvmul<f64,f64>");
}
/// VVDMUL Test
fn vvdmul_test_generic<F, T>(err: &str)
where
F: From<f32> + std::fmt::Debug + PartialEq<F> + MemoryStorable,
T: From<f32> + std::fmt::Debug + PartialEq<T> + MemoryStorable,
{
let mut cpu = CPU::new(0);
let buff: [F; _] = [
1.0.into(),
2.0.into(),
3.0.into(),
4.0.into(),
5.0.into(),
6.0.into(),
7.0.into(),
8.0.into(),
9.0.into(),
10.0.into(),
11.0.into(),
12.0.into(),
13.0.into(),
14.0.into(),
15.0.into(),
16.0.into(),
];
cpu.host().execute_store(0, &buff).unwrap();
let mut inst_builder = InstructionsBuilder::new();
let mut idata_build = InstructionDataBuilder::new();
idata_build.set_core_indx(0).fix_core_indx();
inst_builder.make_inst(sldi, idata_build.set_rdimm(1, 0).build());
inst_builder.make_inst(
sldi,
idata_build.set_rdimm(2, 8 * size_of::<F>() as i32).build(),
);
inst_builder.make_inst(
sldi,
idata_build.set_rdimm(3, 16 * size_of::<F>() as i32).build(),
);
inst_builder.make_inst(
setbw,
idata_build
.set_ibiw_obiw(8 * size_of::<F>() as i32, 8 * size_of::<T>() as i32)
.build(),
);
inst_builder.make_inst(
vvdmul,
idata_build
.set_rdr1r2(3, 1, 2)
.set_imm_len(8 * size_of::<F>() as i32)
.build(),
);
let core_instruction = vec![inst_builder.build().into()];
let mut executable = Executable::new(cpu, core_instruction);
executable.execute();
// Check result correct
assert_eq!(
executable
.cpu_mut()
.host()
.load::<T>(16 * size_of::<F>(), size_of::<T>()).unwrap()[0],
vec![
(492.0).into(),
],
"Wrong result for {}",
err
);
// Check first part equal
assert_eq!(
executable
.cpu_mut()
.host()
.load::<F>(0, 16 * size_of::<F>()).unwrap()[0],
&buff,
"Altered first part for {}",
err
);
//Check that later is 0
assert_eq!(
executable.cpu_mut().host().load::<i32>(
16 * size_of::<F>() + size_of::<T>(),
4 * size_of::<i32>()
).unwrap()[0],
[0, 0, 0, 0],
"Altered first part for {}",
err
);
}
#[test]
fn vvdmul_test() {
vvdmul_test_generic::<f32, f32>("vvdmul<f32,f32>");
vvdmul_test_generic::<f64, f32>("vvdmul<f64,f32>");
vvdmul_test_generic::<f32, f64>("vvdmul<f32,f64>");
vvdmul_test_generic::<f64, f64>("vvdmul<f64,f64>");
}
/// vvmax Test
fn vvmax_test_generic<F, T>(err: &str)
where
F: From<f32> + std::fmt::Debug + PartialEq<F> + MemoryStorable,
T: From<f32> + std::fmt::Debug + PartialEq<T> + MemoryStorable,
{
let mut cpu = CPU::new(0);
let buff: [F; _] = [
9.0.into(),
2.0.into(),
11.0.into(),
4.0.into(),
13.0.into(),
6.0.into(),
7.0.into(),
8.0.into(),
1.0.into(),
10.0.into(),
3.0.into(),
12.0.into(),
4.0.into(),
14.0.into(),
15.0.into(),
16.0.into(),
];
cpu.host().execute_store(0, &buff).unwrap();
let mut inst_builder = InstructionsBuilder::new();
let mut idata_build = InstructionDataBuilder::new();
idata_build.set_core_indx(0).fix_core_indx();
inst_builder.make_inst(sldi, idata_build.set_rdimm(1, 0).build());
inst_builder.make_inst(
sldi,
idata_build.set_rdimm(2, 8 * size_of::<F>() as i32).build(),
);
inst_builder.make_inst(
sldi,
idata_build.set_rdimm(3, 16 * size_of::<F>() as i32).build(),
);
inst_builder.make_inst(
setbw,
idata_build
.set_ibiw_obiw(8 * size_of::<F>() as i32, 8 * size_of::<T>() as i32)
.build(),
);
inst_builder.make_inst(
vvmax,
idata_build
.set_rdr1r2(3, 1, 2)
.set_imm_len(8 * size_of::<F>() as i32)
.build(),
);
let core_instruction = vec![inst_builder.build().into()];
let mut executable = Executable::new(cpu, core_instruction);
executable.execute();
// Check result correct
assert_eq!(
executable
.cpu_mut()
.host()
.load::<T>(16 * size_of::<F>(), 8 * size_of::<T>()).unwrap()[0],
vec![
9.0.into(),
10.0.into(),
11.0.into(),
12.0.into(),
13.0.into(),
14.0.into(),
15.0.into(),
16.0.into(),
],
"Wrong result for {}",
err
);
// Check first part equal
assert_eq!(
executable
.cpu_mut()
.host()
.load::<F>(0, 16 * size_of::<F>()).unwrap()[0],
&buff,
"Altered first part for {}",
err
);
//Check that later is 0
assert_eq!(
executable.cpu_mut().host().load::<i32>(
16 * size_of::<F>() + 8 * size_of::<T>(),
4 * size_of::<i32>()
).unwrap()[0],
[0, 0, 0, 0],
"Altered first part for {}",
err
);
}
#[test]
fn vvmax_test() {
vvmax_test_generic::<f32, f32>("vvmax<f32,f32>");
vvmax_test_generic::<f64, f32>("vvmax<f64,f32>");
vvmax_test_generic::<f32, f64>("vvmax<f32,f64>");
vvmax_test_generic::<f64, f64>("vvmax<f64,f64>");
}
/// vavg Test
fn vavg_test_generic<F, T>(err: &str)
where
F: From<f32> + std::fmt::Debug + PartialEq<F> + MemoryStorable,
T: From<f32> + std::fmt::Debug + PartialEq<T> + MemoryStorable,
{
let mut cpu = CPU::new(0);
let buff: [F; _] = [
9.0.into(),
2.0.into(),
11.0.into(),
4.0.into(),
13.0.into(),
6.0.into(),
7.0.into(),
8.0.into(),
1.0.into(),
10.0.into(),
3.0.into(),
12.0.into(),
4.0.into(),
14.0.into(),
15.0.into(),
16.0.into(),
];
cpu.host().execute_store(0, &buff).unwrap();
let mut inst_builder = InstructionsBuilder::new();
let mut idata_build = InstructionDataBuilder::new();
idata_build.set_core_indx(0).fix_core_indx();
inst_builder.make_inst(sldi, idata_build.set_rdimm(1, 0).build());
inst_builder.make_inst(
sldi,
idata_build.set_rdimm(3, 16 * size_of::<F>() as i32).build(),
);
inst_builder.make_inst(
setbw,
idata_build
.set_ibiw_obiw(8 * size_of::<F>() as i32, 8 * size_of::<T>() as i32)
.build(),
);
inst_builder.make_inst(
vavg,
idata_build
.set_rdr1r2(3, 1, 1)
.set_imm_len(8 * size_of::<F>() as i32)
.build(),
);
let core_instruction = vec![inst_builder.build().into()];
let mut executable = Executable::new(cpu, core_instruction);
executable.execute();
// Check result correct
assert_eq!(
executable
.cpu_mut()
.host()
.load::<T>(16 * size_of::<F>(), size_of::<T>()).unwrap()[0],
vec![
7.5.into(),
],
"Wrong result for {}",
err
);
// Check first part equal
assert_eq!(
executable
.cpu_mut()
.host()
.load::<F>(0, 16 * size_of::<F>()).unwrap()[0],
&buff,
"Altered first part for {}",
err
);
//Check that later is 0
assert_eq!(
executable.cpu_mut().host().load::<i32>(
16 * size_of::<F>() + size_of::<T>(),
4 * size_of::<i32>()
).unwrap()[0],
[0, 0, 0, 0],
"Altered first part for {}",
err
);
}
#[test]
fn vavg_test() {
vavg_test_generic::<f32, f32>("vavg<f32,f32>");
vavg_test_generic::<f64, f32>("vavg<f64,f32>");
vavg_test_generic::<f32, f64>("vavg<f32,f64>");
vavg_test_generic::<f64, f64>("vavg<f64,f64>");
}
/// vrelu Test
fn vrelu_test_generic<F, T>(err: &str)
where
F: From<f32> + std::fmt::Debug + PartialEq<F> + MemoryStorable,
T: From<f32> + std::fmt::Debug + PartialEq<T> + MemoryStorable,
{
let mut cpu = CPU::new(0);
let buff: [F; _] = [
(-9.0).into(),
2.0.into(),
11.0.into(),
(-4.0).into(),
13.0.into(),
(-6.0).into(),
7.0.into(),
(-6.0).into(),
1.0.into(),
(-6.0).into(),
3.0.into(),
12.0.into(),
(-6.0).into(),
14.0.into(),
(-6.0).into(),
16.0.into(),
];
cpu.host().execute_store(0, &buff).unwrap();
let mut inst_builder = InstructionsBuilder::new();
let mut idata_build = InstructionDataBuilder::new();
idata_build.set_core_indx(0).fix_core_indx();
inst_builder.make_inst(sldi, idata_build.set_rdimm(1, 0).build());
inst_builder.make_inst(
sldi,
idata_build.set_rdimm(3, 16 * size_of::<F>() as i32).build(),
);
inst_builder.make_inst(
setbw,
idata_build
.set_ibiw_obiw(8 * size_of::<F>() as i32, 8 * size_of::<T>() as i32)
.build(),
);
inst_builder.make_inst(
vrelu,
idata_build
.set_rdr1r2(3, 1, 1)
.set_imm_len(8 * size_of::<F>() as i32)
.build(),
);
let core_instruction = vec![inst_builder.build().into()];
let mut executable = Executable::new(cpu, core_instruction);
executable.execute();
// Check result correct
assert_eq!(
executable
.cpu_mut()
.host()
.load::<T>(16 * size_of::<F>(), 8*size_of::<T>()).unwrap()[0],
vec![
0.0.into(),
2.0.into(),
11.0.into(),
0.0.into(),
13.0.into(),
0.0.into(),
7.0.into(),
0.0.into(),
],
"Wrong result for {}",
err
);
// Check first part equal
assert_eq!(
executable
.cpu_mut()
.host()
.load::<F>(0, 16 * size_of::<F>()).unwrap()[0],
&buff,
"Altered first part for {}",
err
);
//Check that later is 0
assert_eq!(
executable.cpu_mut().host().load::<i32>(
16 * size_of::<F>() + 8*size_of::<T>(),
4 * size_of::<i32>()
).unwrap()[0],
[0, 0, 0, 0],
"Altered first part for {}",
err
);
}
#[test]
fn vrelu_test() {
vrelu_test_generic::<f32, f32>("vrelu<f32,f32>");
vrelu_test_generic::<f64, f32>("vrelu<f64,f32>");
vrelu_test_generic::<f32, f64>("vrelu<f32,f64>");
vrelu_test_generic::<f64, f64>("vrelu<f64,f64>");
}
/// vtanh Test
fn vtanh_test_generic<F, T>(err: &str)
where
F: From<f32> + std::fmt::Debug + PartialEq<F> + MemoryStorable,
T: From<f32> + std::fmt::Debug + PartialEq<T> + MemoryStorable + UpcastDestTraits<T>,
{
let mut cpu = CPU::new(0);
let buff: [F; _] = [
0.1.into(),
0.2.into(),
0.3.into(),
0.4.into(),
0.5.into(),
0.6.into(),
0.7.into(),
0.8.into(),
0.9.into(),
0.10.into(),
0.11.into(),
0.12.into(),
0.13.into(),
0.14.into(),
0.15.into(),
0.16.into(),
];
cpu.host().execute_store(0, &buff).unwrap();
let mut inst_builder = InstructionsBuilder::new();
let mut idata_build = InstructionDataBuilder::new();
idata_build.set_core_indx(0).fix_core_indx();
inst_builder.make_inst(sldi, idata_build.set_rdimm(1, 0).build());
inst_builder.make_inst(
sldi,
idata_build.set_rdimm(3, 16 * size_of::<F>() as i32).build(),
);
inst_builder.make_inst(
setbw,
idata_build
.set_ibiw_obiw(8 * size_of::<F>() as i32, 8 * size_of::<T>() as i32)
.build(),
);
inst_builder.make_inst(
vtanh,
idata_build
.set_rdr1r2(3, 1, 1)
.set_imm_len(8 * size_of::<F>() as i32)
.build(),
);
let core_instruction = vec![inst_builder.build().into()];
let mut executable = Executable::new(cpu, core_instruction);
executable.execute();
// Check result correct
assert!(
executable
.cpu_mut()
.host()
.load::<T>(16 * size_of::<F>(), 8*size_of::<T>()).unwrap()[0].iter().zip(
vec![
T::from(0.1).tanh(),
T::from(0.2).tanh(),
T::from(0.3).tanh(),
T::from(0.4).tanh(),
T::from(0.5).tanh(),
T::from(0.6).tanh(),
T::from(0.7).tanh(),
T::from(0.8).tanh(),
]).all(|(&a,b) : (&T, T)| {a-b < 0.001.into()}),
"Wrong result for {}",
err
);
// Check first part equal
assert_eq!(
executable
.cpu_mut()
.host()
.load::<F>(0, 16 * size_of::<F>()).unwrap()[0],
&buff,
"Altered first part for {}",
err
);
//Check that later is 0
assert_eq!(
executable.cpu_mut().host().load::<i32>(
16 * size_of::<F>() + 8*size_of::<T>(),
4 * size_of::<i32>()
).unwrap()[0],
[0, 0, 0, 0],
"Altered first part for {}",
err
);
}
#[test]
fn vtanh_test() {
vtanh_test_generic::<f32, f32>("vtanh<f32,f32>");
vtanh_test_generic::<f64, f32>("vtanh<f64,f32>");
vtanh_test_generic::<f32, f64>("vtanh<f32,f64>");
vtanh_test_generic::<f64, f64>("vtanh<f64,f64>");
}
/// vsigm Test
fn vsigm_test_generic<F, T>(err: &str)
where
F: From<f32> + std::fmt::Debug + PartialEq<F> + MemoryStorable,
T: From<f32> + std::fmt::Debug + PartialEq<T> + MemoryStorable + UpcastDestTraits<T>,
{
let mut cpu = CPU::new(0);
let buff: [F; _] = [
0.1.into(),
0.2.into(),
0.3.into(),
0.4.into(),
0.5.into(),
0.6.into(),
0.7.into(),
0.8.into(),
0.9.into(),
0.10.into(),
0.11.into(),
0.12.into(),
0.13.into(),
0.14.into(),
0.15.into(),
0.16.into(),
];
cpu.host().execute_store(0, &buff).unwrap();
let mut inst_builder = InstructionsBuilder::new();
let mut idata_build = InstructionDataBuilder::new();
idata_build.set_core_indx(0).fix_core_indx();
inst_builder.make_inst(sldi, idata_build.set_rdimm(1, 0).build());
inst_builder.make_inst(
sldi,
idata_build.set_rdimm(3, 16 * size_of::<F>() as i32).build(),
);
inst_builder.make_inst(
setbw,
idata_build
.set_ibiw_obiw(8 * size_of::<F>() as i32, 8 * size_of::<T>() as i32)
.build(),
);
inst_builder.make_inst(
vsigm,
idata_build
.set_rdr1r2(3, 1, 1)
.set_imm_len(8 * size_of::<F>() as i32)
.build(),
);
let core_instruction = vec![inst_builder.build().into()];
let mut executable = Executable::new(cpu, core_instruction);
executable.execute();
// Check result correct
assert!(
executable
.cpu_mut()
.host()
.load::<T>(16 * size_of::<F>(), 8*size_of::<T>()).unwrap()[0].iter().zip(
vec![
T::from(0.1).sigm(),
T::from(0.2).sigm(),
T::from(0.3).sigm(),
T::from(0.4).sigm(),
T::from(0.5).sigm(),
T::from(0.6).sigm(),
T::from(0.7).sigm(),
T::from(0.8).sigm(),
]).all(|(&a,b) : (&T, T)| {a-b < 0.001.into()}),
"Wrong result for {}",
err
);
// Check first part equal
assert_eq!(
executable
.cpu_mut()
.host()
.load::<F>(0, 16 * size_of::<F>()).unwrap()[0],
&buff,
"Altered first part for {}",
err
);
//Check that later is 0
assert_eq!(
executable.cpu_mut().host().load::<i32>(
16 * size_of::<F>() + 8*size_of::<T>(),
4 * size_of::<i32>()
).unwrap()[0],
[0, 0, 0, 0],
"Altered first part for {}",
err
);
}
#[test]
fn vsigm_test() {
vsigm_test_generic::<f32, f32>("vsigm<f32,f32>");
vsigm_test_generic::<f64, f32>("vsigm<f64,f32>");
vsigm_test_generic::<f32, f64>("vsigm<f32,f64>");
vsigm_test_generic::<f64, f64>("vsigm<f64,f64>");
}
/// mvmul Test
fn mvmul_test_generic<F,M, T>(err: &str, relu:i32)
where
F: From<f32> + std::fmt::Debug + PartialEq<F> + MemoryStorable,
M: From<f32> + std::fmt::Debug + PartialEq<M> + MemoryStorable,
T: From<f32> + std::fmt::Debug + PartialEq<T> + MemoryStorable + UpcastDestTraits<T>,
{
let mut cpu = CPU::new(0);
cpu.reserve_crossbar(1, 4 * size_of::<M>(), 4);
let (memory, crossbars) = cpu.host().get_memory_crossbar();
let matrix: [M; _] = [
1.0.into(),
2.0.into(),
3.0.into(),
4.0.into(),
5.0.into(),
(-56.0).into(),
7.0.into(),
8.0.into(),
9.0.into(),
10.0.into(),
11.0.into(),
12.0.into(),
13.0.into(),
14.0.into(),
15.0.into(),
16.0.into(),
];
crossbars.get_mut(0).unwrap().execute_store( &matrix).unwrap();
let vector: [F; _] = [
1.0.into(),
2.0.into(),
3.0.into(),
4.0.into(),
];
memory.execute_store(0, &vector).unwrap();
let mut inst_builder = InstructionsBuilder::new();
let mut idata_build = InstructionDataBuilder::new();
idata_build.set_core_indx(0).fix_core_indx();
inst_builder.make_inst(sldi, idata_build.set_rdimm(1, 0).build());
inst_builder.make_inst(
sldi,
idata_build.set_rdimm(3, 4 * size_of::<F>() as i32).build(),
);
inst_builder.make_inst(
setbw,
idata_build
.set_ibiw_obiw(8 * size_of::<F>() as i32, 8 * size_of::<T>() as i32)
.build(),
);
inst_builder.make_inst(
mvmul,
idata_build
.set_rdr1(3, 1)
.set_mbiw_immrelu_immgroup(8*size_of::<M>() as i32, relu, 0)
.build(),
);
let core_instruction = vec![inst_builder.build().into()];
let mut executable = Executable::new(cpu, core_instruction);
executable.execute();
// Check result correct
if relu == 0 {
assert_eq!(
executable
.cpu_mut()
.host()
.load::<T>(4 * size_of::<F>(), 4*size_of::<T>()).unwrap()[0],
vec![
90.0.into(),
(-24.0).into(),
110.0.into(),
120.0.into(),
],
"Wrong result for {}",
err
);
}
else {
assert_eq!(
executable
.cpu_mut()
.host()
.load::<T>(4 * size_of::<F>(), 4*size_of::<T>()).unwrap()[0],
vec![
90.0.into(),
0.0.into(),
110.0.into(),
120.0.into(),
],
"Wrong result for {}",
err
);
}
// Check first part equal
assert_eq!(
executable
.cpu_mut()
.host()
.load::<F>(0, 4 * size_of::<F>()).unwrap()[0],
&vector,
"Altered first part for {}",
err
);
//Check that later is 0
assert_eq!(
executable.cpu_mut().host().load::<i32>(
4 * size_of::<F>() + 4*size_of::<T>(),
4 * size_of::<i32>()
).unwrap()[0],
[0, 0, 0, 0],
"Altered first part for {}",
err
);
}
#[test]
fn mvmul_test() {
mvmul_test_generic::<f32,f32,f32>("mvmul<f32,f32,f32>",0);
mvmul_test_generic::<f32,f32,f64>("mvmul<f32,f32,f64>",0);
mvmul_test_generic::<f32,f64,f32>("mvmul<f32,f64,f32>",0);
mvmul_test_generic::<f32,f64,f64>("mvmul<f32,f64,f64>",0);
mvmul_test_generic::<f64,f32,f32>("mvmul<f64,f32,f32>",0);
mvmul_test_generic::<f64,f32,f64>("mvmul<f64,f32,f64>",0);
mvmul_test_generic::<f64,f64,f32>("mvmul<f64,f64,f32>",0);
mvmul_test_generic::<f64,f64,f64>("mvmul<f64,f64,f64>",0);
mvmul_test_generic::<f32,f32,f32>("mvmul<f32,f32,f32>",1);
mvmul_test_generic::<f32,f32,f64>("mvmul<f32,f32,f64>",1);
mvmul_test_generic::<f32,f64,f32>("mvmul<f32,f64,f32>",1);
mvmul_test_generic::<f32,f64,f64>("mvmul<f32,f64,f64>",1);
mvmul_test_generic::<f64,f32,f32>("mvmul<f64,f32,f32>",1);
mvmul_test_generic::<f64,f32,f64>("mvmul<f64,f32,f64>",1);
mvmul_test_generic::<f64,f64,f32>("mvmul<f64,f64,f32>",1);
mvmul_test_generic::<f64,f64,f64>("mvmul<f64,f64,f64>",1);
}