Skip to content

Commit 0a59398

Browse files
committed
WIP
1 parent 7026b09 commit 0a59398

File tree

4 files changed

+199
-81
lines changed

4 files changed

+199
-81
lines changed

crates/intrinsic-test/src/arm/mod.rs

Lines changed: 78 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,10 @@ mod types;
1111
use crate::common::SupportedArchitectureTest;
1212
use crate::common::cli::ProcessedCli;
1313
use crate::common::compare::compare_outputs;
14+
use crate::common::gen_c::{write_main_cpp, write_mod_cpp};
1415
use crate::common::gen_rust::{compile_rust_programs, write_cargo_toml, write_main_rs};
1516
use crate::common::intrinsic::Intrinsic;
1617
use crate::common::intrinsic_helpers::TypeKind;
17-
use crate::common::write_file::write_c_testfiles;
18-
use compile::compile_c_arm;
1918
use config::{AARCH_CONFIGURATIONS, F16_FORMATTING_DEF, POLY128_OSTREAM_DEF, build_notices};
2019
use intrinsic::ArmIntrinsicType;
2120
use json_parser::get_neon_intrinsics;
@@ -60,24 +59,86 @@ impl SupportedArchitectureTest for ArmArchitectureTest {
6059
let cxx_toolchain_dir = self.cli_options.cxx_toolchain_dir.as_deref();
6160
let c_target = "aarch64";
6261

63-
let intrinsics_name_list = write_c_testfiles(
64-
self.intrinsics.par_iter(),
65-
target,
62+
let available_parallelism = std::thread::available_parallelism().unwrap().get();
63+
let chunk_size = self.intrinsics.len().div_ceil(available_parallelism);
64+
65+
let notice = &build_notices("// ");
66+
self.intrinsics
67+
.par_chunks(chunk_size)
68+
.enumerate()
69+
.map(|(i, chunk)| {
70+
let c_filename = format!("c_programs/mod_{i}.cpp");
71+
let mut file = File::create(&c_filename).unwrap();
72+
write_mod_cpp(&mut file, &notice, chunk).unwrap();
73+
74+
// compile this cpp file into a .o file
75+
76+
// clang++ -march=armv8.6-a+crypto+crc+dotprod+fp16+faminmax+lut+sha3 -O2 -ffp-contract=off -Wno-narrowing --target=aarch64-unknown-linux-gnu c_file_0.c -c
77+
let mut cmd = std::process::Command::new("clang++");
78+
cmd.current_dir("c_programs");
79+
80+
cmd.arg("-march=armv8.6-a+crypto+crc+dotprod+fp16+faminmax+lut+sha3");
81+
cmd.arg("-O2");
82+
cmd.arg("-ffp-contract=off");
83+
cmd.arg("-Wno-narrowing");
84+
cmd.arg("--target=aarch64-unknown-linux-gnu");
85+
cmd.arg("-c");
86+
cmd.arg(format!("mod_{i}.cpp"));
87+
88+
let output = cmd.output();
89+
eprintln!(
90+
"{}",
91+
String::from_utf8_lossy(&output.as_ref().unwrap().stderr)
92+
);
93+
assert!(output.unwrap().status.success());
94+
95+
Ok(())
96+
})
97+
.collect::<Result<(), std::io::Error>>()
98+
.unwrap();
99+
100+
let c_filename = format!("c_programs/main.cpp");
101+
let mut file = File::create(&c_filename).unwrap();
102+
write_main_cpp(
103+
&mut file,
66104
c_target,
67-
&["arm_neon.h", "arm_acle.h", "arm_fp16.h"],
68-
&build_notices("// "),
69-
&[POLY128_OSTREAM_DEF],
70-
);
105+
POLY128_OSTREAM_DEF,
106+
self.intrinsics.iter().map(|i| i.name.as_str()),
107+
)
108+
.unwrap();
71109

72-
match compiler {
73-
None => true,
74-
Some(compiler) => compile_c_arm(
75-
intrinsics_name_list.unwrap().as_slice(),
76-
compiler,
77-
target,
78-
cxx_toolchain_dir,
79-
),
110+
let mut cmd = std::process::Command::new("clang++");
111+
cmd.current_dir("c_programs");
112+
113+
cmd.arg("-march=armv8.6-a+crypto+crc+dotprod+fp16+faminmax+lut+sha3");
114+
cmd.arg("-O2");
115+
cmd.arg("-ffp-contract=off");
116+
cmd.arg("-Wno-narrowing");
117+
cmd.arg("--target=aarch64-unknown-linux-gnu");
118+
cmd.arg(format!("main.cpp"));
119+
for i in 0..Ord::min(available_parallelism, self.intrinsics.len()) {
120+
cmd.arg(format!("mod_{i}.o"));
80121
}
122+
cmd.args(&["-o", "intrinsic-test-programs"]);
123+
124+
let output = cmd.output();
125+
eprintln!(
126+
"{}",
127+
String::from_utf8_lossy(&output.as_ref().unwrap().stderr)
128+
);
129+
assert!(output.unwrap().status.success());
130+
131+
// match compiler {
132+
// None => true,
133+
// Some(compiler) => compile_c_arm(
134+
// intrinsics_name_list.unwrap().as_slice(),
135+
// compiler,
136+
// target,
137+
// cxx_toolchain_dir,
138+
// ),
139+
// }
140+
141+
true
81142
}
82143

83144
fn build_rust_file(&self) -> bool {

crates/intrinsic-test/src/common/compare.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@ pub fn compare_outputs(intrinsic_name_list: &Vec<String>, runner: &str, target:
1515
.par_iter()
1616
.filter_map(|intrinsic_name| {
1717
let c = runner_command(runner)
18-
.arg(format!("./c_programs/{intrinsic_name}"))
18+
.arg("intrinsic-test-programs")
19+
.arg(intrinsic_name)
20+
.current_dir("c_programs")
1921
.output();
2022

2123
let rust = runner_command(runner)

crates/intrinsic-test/src/common/gen_c.rs

Lines changed: 79 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ pub fn generate_c_test_loop<T: IntrinsicTypeDefinition + Sized>(
4242
passes: u32,
4343
) -> std::io::Result<()> {
4444
let body_indentation = indentation.nested();
45-
write!(
45+
writeln!(
4646
w,
4747
"{indentation}for (int i=0; i<{passes}; i++) {{\n\
4848
{loaded_args}\
@@ -89,20 +89,40 @@ pub fn generate_c_constraint_blocks<'a, T: IntrinsicTypeDefinition + 'a>(
8989
}
9090

9191
// Compiles C test programs using specified compiler
92-
pub fn create_c_test_program<T: IntrinsicTypeDefinition>(
92+
pub fn create_c_test_function<T: IntrinsicTypeDefinition>(
9393
w: &mut impl std::io::Write,
9494
intrinsic: &dyn IntrinsicDefinition<T>,
95-
header_files: &[&str],
96-
_target: &str,
97-
c_target: &str,
98-
notices: &str,
99-
arch_specific_definitions: &[&str],
10095
) -> std::io::Result<()> {
10196
let indentation = Indentation::default();
10297

103-
write!(w, "{notices}")?;
98+
writeln!(w, "int run_{}() {{", intrinsic.name())?;
99+
100+
// Define the arrays of arguments.
101+
let arguments = intrinsic.arguments();
102+
arguments.gen_arglists_c(w, indentation.nested(), PASSES)?;
104103

105-
for header in header_files {
104+
generate_c_constraint_blocks(
105+
w,
106+
intrinsic,
107+
indentation.nested(),
108+
&mut arguments.iter().rev().filter(|&i| i.has_constraint()),
109+
Default::default(),
110+
)?;
111+
112+
writeln!(w, " return 0;")?;
113+
writeln!(w, "}}")?;
114+
115+
Ok(())
116+
}
117+
118+
pub fn write_mod_cpp<T: IntrinsicTypeDefinition>(
119+
w: &mut impl std::io::Write,
120+
notice: &str,
121+
intrinsics: &[impl IntrinsicDefinition<T>],
122+
) -> std::io::Result<()> {
123+
write!(w, "{notice}")?;
124+
125+
for header in ["arm_neon.h", "arm_acle.h", "arm_fp16.h"] {
106126
writeln!(w, "#include <{header}>")?;
107127
}
108128

@@ -121,6 +141,38 @@ template<typename T1, typename T2> T1 cast(T2 x) {{
121141
return ret;
122142
}}
123143
144+
std::ostream& operator<<(std::ostream& os, float16_t value);
145+
std::ostream& operator<<(std::ostream& os, poly128_t value);
146+
"#
147+
)?;
148+
149+
for intrinsic in intrinsics {
150+
create_c_test_function(w, intrinsic)?;
151+
}
152+
153+
Ok(())
154+
}
155+
156+
pub fn write_main_cpp<'a>(
157+
w: &mut impl std::io::Write,
158+
architecture: &str,
159+
arch_specific_definitions: &str,
160+
intrinsics: impl Iterator<Item = &'a str> + Clone,
161+
) -> std::io::Result<()> {
162+
writeln!(w, "#include <iostream>")?;
163+
writeln!(w, "#include <string>")?;
164+
165+
for header in ["arm_neon.h", "arm_acle.h", "arm_fp16.h"] {
166+
writeln!(w, "#include <{header}>")?;
167+
}
168+
169+
writeln!(
170+
w,
171+
r#"
172+
#include <cstring>
173+
#include <iomanip>
174+
#include <sstream>
175+
124176
std::ostream& operator<<(std::ostream& os, float16_t value) {{
125177
uint16_t temp = 0;
126178
memcpy(&temp, &value, sizeof(float16_t));
@@ -132,28 +184,32 @@ std::ostream& operator<<(std::ostream& os, float16_t value) {{
132184
"#
133185
)?;
134186

135-
let arch_identifier = c_target;
136-
writeln!(w, "#ifdef __{arch_identifier}__")?;
137-
for def in arch_specific_definitions {
138-
writeln!(w, "{def}")?;
139-
}
187+
writeln!(w, "#ifdef __{architecture}__")?;
188+
writeln!(w, "{arch_specific_definitions }")?;
140189
writeln!(w, "#endif")?;
141190

191+
for intrinsic in intrinsics.clone() {
192+
writeln!(w, "extern int run_{intrinsic}(void);")?;
193+
}
194+
142195
writeln!(w, "int main(int argc, char **argv) {{")?;
196+
writeln!(w, " std::string intrinsic_name = argv[1];")?;
143197

144-
// Define the arrays of arguments.
145-
let arguments = intrinsic.arguments();
146-
arguments.gen_arglists_c(w, indentation.nested(), PASSES)?;
198+
writeln!(w, " if (false) {{")?;
147199

148-
generate_c_constraint_blocks(
200+
for intrinsic in intrinsics {
201+
writeln!(w, " }} else if (intrinsic_name == \"{intrinsic}\") {{")?;
202+
writeln!(w, " return run_{intrinsic}();")?;
203+
}
204+
205+
writeln!(w, " }} else {{")?;
206+
writeln!(
149207
w,
150-
intrinsic,
151-
indentation.nested(),
152-
&mut arguments.iter().rev().filter(|&i| i.has_constraint()),
153-
Default::default(),
208+
" std::cerr << \"Unknown command: \" << intrinsic_name << \"\\n\";"
154209
)?;
210+
writeln!(w, " return -1;")?;
211+
writeln!(w, " }}")?;
155212

156-
writeln!(w, " return 0;")?;
157213
writeln!(w, "}}")?;
158214

159215
Ok(())
Lines changed: 39 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,40 @@
1-
use std::fs::File;
1+
// use std::fs::File;
2+
//
3+
// use super::intrinsic::IntrinsicDefinition;
4+
// use super::intrinsic_helpers::IntrinsicTypeDefinition;
5+
//
6+
// use rayon::prelude::*;
27

3-
use super::intrinsic::IntrinsicDefinition;
4-
use super::intrinsic_helpers::IntrinsicTypeDefinition;
5-
6-
use rayon::prelude::*;
7-
8-
pub fn write_c_testfiles<'a, T, I, E>(
9-
intrinsics: I,
10-
target: &str,
11-
c_target: &str,
12-
headers: &[&str],
13-
notice: &str,
14-
arch_specific_definitions: &[&str],
15-
) -> std::io::Result<Vec<String>>
16-
where
17-
T: IntrinsicTypeDefinition + Sized + 'a,
18-
I: ParallelIterator<Item = &'a E>,
19-
E: IntrinsicDefinition<T> + 'a,
20-
{
21-
std::fs::create_dir_all("c_programs")?;
22-
23-
intrinsics
24-
.map(|intrinsic| {
25-
let identifier = intrinsic.name().to_owned();
26-
let mut file = File::create(format!("c_programs/{identifier}.cpp")).unwrap();
27-
28-
crate::common::gen_c::create_c_test_program(
29-
&mut file,
30-
intrinsic,
31-
headers,
32-
target,
33-
c_target,
34-
notice,
35-
arch_specific_definitions,
36-
)?;
37-
38-
Ok(identifier)
39-
})
40-
.collect()
41-
}
8+
// pub fn write_c_testfiles<'a, T, I, E>(
9+
// intrinsics: I,
10+
// target: &str,
11+
// c_target: &str,
12+
// headers: &[&str],
13+
// notice: &str,
14+
// arch_specific_definitions: &[&str],
15+
// ) -> std::io::Result<Vec<String>>
16+
// where
17+
// T: IntrinsicTypeDefinition + Sized + 'a,
18+
// I: ParallelIterator<Item = &'a E>,
19+
// E: IntrinsicDefinition<T> + 'a,
20+
// {
21+
// std::fs::create_dir_all("c_programs")?;
22+
//
23+
// intrinsics
24+
// .map(|intrinsic| {
25+
// let identifier = intrinsic.name().to_owned();
26+
// let mut file = File::create(format!("c_programs/{identifier}.cpp")).unwrap();
27+
//
28+
// crate::common::gen_c::create_c_test_function(
29+
// &mut file,
30+
// intrinsic,
31+
//
32+
//
33+
//
34+
//
35+
// )?;
36+
//
37+
// Ok(identifier)
38+
// })
39+
// .collect()
40+
// }

0 commit comments

Comments
 (0)