forked from libre-chip/cpu
add build script that parses the PowerISA v3.1C pdf and produces an xml file
This commit is contained in:
parent
3b5104c8fa
commit
e4a7d9f59c
4 changed files with 548 additions and 17 deletions
|
|
@ -18,3 +18,10 @@ version.workspace = true
|
|||
fayalite.workspace = true
|
||||
serde.workspace = true
|
||||
simple-mermaid.workspace = true
|
||||
|
||||
[build-dependencies]
|
||||
base16ct.workspace = true
|
||||
hex-literal.workspace = true
|
||||
parse_powerisa_pdf.workspace = true
|
||||
sha2.workspace = true
|
||||
ureq.workspace = true
|
||||
|
|
|
|||
93
crates/cpu/build.rs
Normal file
93
crates/cpu/build.rs
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
use parse_powerisa_pdf::parse_powerisa_pdf_and_generate_xml;
|
||||
use sha2::{Digest, Sha256};
|
||||
use std::{
|
||||
error::Error,
|
||||
io::{ErrorKind, Read},
|
||||
path::Path,
|
||||
};
|
||||
|
||||
const EXPECTED_FILE_SIZE: u64 = 6425593;
|
||||
const EXPECTED_FILE_HASH: &[u8; 32] =
|
||||
&hex_literal::hex!("56372d23ece7e9e2c1b381a639443982a3e16e38109df1c141d655b779b61fdb");
|
||||
|
||||
fn verify_powerisa_file(file: impl std::io::Read) -> Result<Vec<u8>, Box<dyn Error>> {
|
||||
let mut buf = Vec::with_capacity(usize::try_from(EXPECTED_FILE_SIZE)? + 1);
|
||||
file.take(EXPECTED_FILE_SIZE + 1).read_to_end(&mut buf)?;
|
||||
if buf.len() > EXPECTED_FILE_SIZE as usize {
|
||||
Err(format!("file is bigger than the expected length {EXPECTED_FILE_SIZE}").into())
|
||||
} else if buf.len() < EXPECTED_FILE_SIZE as usize {
|
||||
Err(format!(
|
||||
"file is smaller than the expected length {EXPECTED_FILE_SIZE}: actual length {}",
|
||||
buf.len()
|
||||
)
|
||||
.into())
|
||||
} else {
|
||||
let hash = Sha256::digest(&buf);
|
||||
let hash = &*hash;
|
||||
if hash != EXPECTED_FILE_HASH {
|
||||
Err(format!(
|
||||
"file's SHA256 hash doesn't match the expected hash: expected: {:x} got: {:x}",
|
||||
base16ct::HexDisplay(EXPECTED_FILE_HASH),
|
||||
base16ct::HexDisplay(hash)
|
||||
)
|
||||
.into())
|
||||
} else {
|
||||
Ok(buf)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn is_powerisa_pdf(path: impl AsRef<Path>) -> Result<bool, Box<dyn Error>> {
|
||||
let path = path.as_ref();
|
||||
let metadata = match std::fs::metadata(path) {
|
||||
Err(e) if e.kind() == ErrorKind::NotFound => return Ok(false),
|
||||
v => v?,
|
||||
};
|
||||
if !metadata.is_file() {
|
||||
return Ok(false);
|
||||
}
|
||||
let file = std::fs::File::open(path)?;
|
||||
verify_powerisa_file(file)?;
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
fn out_dir() -> String {
|
||||
std::env::var("OUT_DIR").expect("OUT_DIR env var is not set or invalid")
|
||||
}
|
||||
|
||||
fn get_powerisa_pdf_name_and_dir<'a>(
|
||||
out_dir: &'a str,
|
||||
) -> Result<(&'static str, &'a Path), Box<dyn Error>> {
|
||||
const FILE_NAME: &str = "OPF_PowerISA_v3.1C.pdf";
|
||||
let out_dir = Path::new(out_dir);
|
||||
if is_powerisa_pdf(FILE_NAME)? {
|
||||
println!("cargo::rerun-if-changed={FILE_NAME}");
|
||||
return Ok((FILE_NAME, Path::new(".")));
|
||||
}
|
||||
let full_path = out_dir.join(FILE_NAME);
|
||||
let full_path = full_path
|
||||
.into_os_string()
|
||||
.into_string()
|
||||
.expect("should be valid UTF-8");
|
||||
if is_powerisa_pdf(&full_path)? {
|
||||
println!("cargo::rerun-if-changed={full_path}");
|
||||
return Ok((FILE_NAME, out_dir));
|
||||
}
|
||||
const URL: &str = "https://libre-chip.org/OPF_PowerISA_v3.1C.pdf";
|
||||
println!("cargo::warning={FILE_NAME} not found locally, downloading from {URL}");
|
||||
let buf = verify_powerisa_file(ureq::get(URL).call()?.into_body().into_reader())?;
|
||||
std::fs::write(&full_path, buf)?;
|
||||
println!("cargo::rerun-if-changed={full_path}");
|
||||
Ok((FILE_NAME, out_dir))
|
||||
}
|
||||
|
||||
fn main() -> Result<(), Box<dyn Error>> {
|
||||
let out_dir = out_dir();
|
||||
let (pdf_name, pdf_dir) = get_powerisa_pdf_name_and_dir(&out_dir)?;
|
||||
let old_dir = std::env::current_dir()?;
|
||||
std::env::set_current_dir(pdf_dir)?;
|
||||
let xml = parse_powerisa_pdf_and_generate_xml(pdf_name, None, false)?;
|
||||
std::env::set_current_dir(old_dir)?;
|
||||
std::fs::write(Path::new(&out_dir).join("powerisa-instructions.xml"), xml)?;
|
||||
Ok(())
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue