use std::path::Path;

use pimcore::{Executable, cpu::CPU, instruction_set::{InstructionsBuilder, instruction_data::InstructionDataBuilder, isa::*}};

fn simple_read(path:  &Path) -> Vec<f32> {
    if !path.exists() {
        panic!("{:?} not exists", path)
    }
    std::fs::read_to_string(path)
        .unwrap()
        .split(',')
        .map(|s| s.trim().parse::<f32>().unwrap())
        .collect()
}

/// mvmul Test
fn mvmul_f32(err: &str)
where
{
    let mut cpu = CPU::new(0);
    cpu.reserve_crossbar(1, 1024 * size_of::<f32>(),  1024);
    let (memory, crossbars) = cpu.host().get_memory_crossbar();
    let matrix = simple_read(Path::new("B.txt")) ;

    
    crossbars.get_mut(0).unwrap().execute_store( &matrix).unwrap();
    let vector = simple_read(Path::new("A.txt"));
    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, 1024 * size_of::<f32>() as i32).build(),
    );
    inst_builder.make_inst(
        setbw,
        idata_build
            .set_ibiw_obiw(8 * size_of::<f32>() as i32, 8 * size_of::<f32>() as i32)
            .build(),
    );
    inst_builder.make_inst(
        mvmul,
        idata_build
            .set_rdr1(3, 1)
            .set_mbiw_immrelu_immgroup(8*size_of::<f32>() as i32, 0, 0)
            .build(),
    );
    let core_instruction = vec![inst_builder.build().into()];
    let mut executable = Executable::new(cpu, core_instruction);
    executable.execute();

    assert!(
        executable
            .cpu_mut()
            .host()
            .load::<f32>(1024 * size_of::<f32>(), 1024*size_of::<f32>()).unwrap()[0].iter().zip(
        simple_read(Path::new("X.txt")) ).all(|(&a,b) : (&f32, f32)| {a-b < 0.001}),
        "Wrong result for {}",
        err
    );
}

#[test]
fn mvmul_big_test() {
    mvmul_f32("mvmul_f32");
   

}


