diff --git a/crates/fayalite/src/build.rs b/crates/fayalite/src/build.rs index 96492cf9..46591238 100644 --- a/crates/fayalite/src/build.rs +++ b/crates/fayalite/src/build.rs @@ -31,20 +31,17 @@ pub mod firrtl; pub mod formal; pub mod graph; pub mod registry; -pub mod vendor; pub mod verilog; -pub(crate) fn built_in_job_kinds() -> impl IntoIterator { - [ - DynJobKind::new(BaseJobKind), - DynJobKind::new(CreateOutputDirJobKind), - ] - .into_iter() - .chain(firrtl::built_in_job_kinds()) - .chain(formal::built_in_job_kinds()) - .chain(vendor::built_in_job_kinds()) - .chain(verilog::built_in_job_kinds()) -} +pub(crate) const BUILT_IN_JOB_KINDS: &'static [fn() -> DynJobKind] = &[ + || DynJobKind::new(BaseJobKind), + || DynJobKind::new(CreateOutputDirJobKind), + || DynJobKind::new(firrtl::FirrtlJobKind), + || DynJobKind::new(external::ExternalCommandJobKind::::new()), + || DynJobKind::new(verilog::VerilogJobKind), + || DynJobKind::new(formal::WriteSbyFileJobKind), + || DynJobKind::new(external::ExternalCommandJobKind::::new()), +]; #[track_caller] fn intern_known_utf8_path_buf(v: PathBuf) -> Interned { @@ -102,7 +99,7 @@ impl JobItem { } } -#[derive(Copy, Clone, Hash, PartialEq, Eq, Debug, Serialize, Deserialize)] +#[derive(Copy, Clone, Hash, PartialEq, Eq, Debug)] #[non_exhaustive] pub enum JobItemName { Path { path: Interned }, @@ -174,30 +171,12 @@ pub trait WriteArgs: fn write_interned_arg(&mut self, arg: Interned) { self.extend([arg]); } - /// finds the first option that is `--{option_name}={value}` and returns `value` - fn get_long_option_eq(&self, option_name: impl AsRef) -> Option<&str>; } -pub struct ArgsWriter(pub Vec); +#[derive(Default)] +struct WriteArgsWrapper(W); -impl Default for ArgsWriter { - fn default() -> Self { - Self(Default::default()) - } -} - -impl> ArgsWriter { - fn get_long_option_eq_helper(&self, option_name: &str) -> Option<&str> { - self.0.iter().find_map(|arg| { - arg.as_ref() - .strip_prefix("--") - .and_then(|arg| arg.strip_prefix(option_name)) - .and_then(|arg| arg.strip_prefix("=")) - }) - } -} - -impl<'a, W> Extend> for ArgsWriter +impl<'a, W> Extend> for WriteArgsWrapper where Self: Extend, { @@ -206,47 +185,39 @@ where } } -impl<'a> Extend<&'a str> for ArgsWriter> { +impl<'a> Extend<&'a str> for WriteArgsWrapper>> { fn extend>(&mut self, iter: T) { self.extend(iter.into_iter().map(str::intern)) } } -impl Extend for ArgsWriter> { +impl Extend for WriteArgsWrapper>> { fn extend>(&mut self, iter: T) { self.extend(iter.into_iter().map(str::intern_owned)) } } -impl Extend> for ArgsWriter { +impl Extend> for WriteArgsWrapper> { fn extend>>(&mut self, iter: T) { self.extend(iter.into_iter().map(String::from)) } } -impl<'a> Extend<&'a str> for ArgsWriter { +impl<'a> Extend<&'a str> for WriteArgsWrapper> { fn extend>(&mut self, iter: T) { self.extend(iter.into_iter().map(String::from)) } } -impl Extend for ArgsWriter { +impl Extend for WriteArgsWrapper> { fn extend>(&mut self, iter: T) { self.0.extend(iter); } } -impl WriteArgs for ArgsWriter { - fn get_long_option_eq(&self, option_name: impl AsRef) -> Option<&str> { - self.get_long_option_eq_helper(option_name.as_ref()) - } -} +impl WriteArgs for WriteArgsWrapper> {} -impl WriteArgs for ArgsWriter> { - fn get_long_option_eq(&self, option_name: impl AsRef) -> Option<&str> { - self.get_long_option_eq_helper(option_name.as_ref()) - } -} +impl WriteArgs for WriteArgsWrapper>> {} pub trait ToArgs: clap::Args + 'static + Send + Sync + Hash + Eq + fmt::Debug + Clone { fn to_args(&self, args: &mut (impl WriteArgs + ?Sized)); @@ -254,12 +225,12 @@ pub trait ToArgs: clap::Args + 'static + Send + Sync + Hash + Eq + fmt::Debug + Intern::intern_owned(self.to_interned_args_vec()) } fn to_interned_args_vec(&self) -> Vec> { - let mut retval = ArgsWriter::default(); + let mut retval = WriteArgsWrapper::default(); self.to_args(&mut retval); retval.0 } fn to_string_args(&self) -> Vec { - let mut retval = ArgsWriter::default(); + let mut retval = WriteArgsWrapper::default(); self.to_args(&mut retval); retval.0 } @@ -671,9 +642,6 @@ pub trait JobKind: 'static + Send + Sync + Hash + Eq + fmt::Debug + Sized + Copy fn subcommand_hidden(self) -> bool { false } - fn external_program(self) -> Option> { - None - } } trait DynJobKindTrait: 'static + Send + Sync + fmt::Debug { @@ -1042,7 +1010,7 @@ impl DynJobArgsTrait for DynJobArgsInner { } fn to_args_extend_vec(&self, args: Vec>) -> Vec> { - let mut writer = ArgsWriter(args); + let mut writer = WriteArgsWrapper(args); self.0.args.to_args(&mut writer); writer.0 } diff --git a/crates/fayalite/src/build/external.rs b/crates/fayalite/src/build/external.rs index 0779ed64..8c6858a7 100644 --- a/crates/fayalite/src/build/external.rs +++ b/crates/fayalite/src/build/external.rs @@ -3,9 +3,9 @@ use crate::{ build::{ - ArgsWriter, CommandParams, GetBaseJob, JobAndDependencies, JobAndKind, - JobArgsAndDependencies, JobDependencies, JobItem, JobItemName, JobKind, JobKindAndArgs, - JobParams, ToArgs, WriteArgs, intern_known_utf8_path_buf, + CommandParams, GetBaseJob, JobAndDependencies, JobAndKind, JobArgsAndDependencies, + JobDependencies, JobItem, JobItemName, JobKind, JobKindAndArgs, JobParams, ToArgs, + WriteArgs, intern_known_utf8_path_buf, }, intern::{Intern, Interned}, util::{job_server::AcquiredJob, streaming_read_utf8::streaming_read_utf8}, @@ -431,7 +431,7 @@ impl ExternalCommandJobKind { } #[derive(Copy, Clone)] -struct ExternalProgramPathValueParser(ExternalProgram); +struct ExternalCommandProgramPathValueParser(PhantomData); fn parse_which_result( which_result: which::Result, @@ -460,7 +460,9 @@ fn parse_which_result( )) } -impl clap::builder::TypedValueParser for ExternalProgramPathValueParser { +impl clap::builder::TypedValueParser + for ExternalCommandProgramPathValueParser +{ type Value = Interned; fn parse_ref( @@ -469,11 +471,10 @@ impl clap::builder::TypedValueParser for ExternalProgramPathValueParser { arg: Option<&clap::Arg>, value: &OsStr, ) -> clap::error::Result { - let program_path_arg_name = self.0.program_path_arg_name; OsStringValueParser::new() - .try_map(move |program_name| { + .try_map(|program_name| { parse_which_result(which::which(&program_name), program_name, || { - program_path_arg_name.into() + T::program_path_arg_name().into() }) }) .parse_ref(cmd, arg, value) @@ -484,8 +485,16 @@ impl clap::builder::TypedValueParser for ExternalProgramPathValueParser { #[group(id = T::args_group_id())] #[non_exhaustive] pub struct ExternalCommandArgs { - #[command(flatten)] - pub program_path: ExternalProgramPath, + #[arg( + name = Interned::into_inner(T::program_path_arg_name()), + long = T::program_path_arg_name(), + value_name = T::program_path_arg_value_name(), + env = T::program_path_env_var_name().map(Interned::into_inner), + value_parser = ExternalCommandProgramPathValueParser::(PhantomData), + default_value = T::default_program_name(), + value_hint = clap::ValueHint::CommandName, + )] + pub program_path: Interned, #[arg( name = Interned::into_inner(T::run_even_if_cached_arg_name()), long = T::run_even_if_cached_arg_name(), @@ -566,15 +575,6 @@ impl ExternalCommandArgs { pub fn with_resolved_program_path( program_path: Interned, additional_args: T::AdditionalArgs, - ) -> Self { - Self::new( - ExternalProgramPath::with_resolved_program_path(program_path), - additional_args, - ) - } - pub fn new( - program_path: ExternalProgramPath, - additional_args: T::AdditionalArgs, ) -> Self { Self { program_path, @@ -582,12 +582,16 @@ impl ExternalCommandArgs { additional_args, } } - pub fn resolve_program_path( + pub fn new( program_name: Option<&OsStr>, additional_args: T::AdditionalArgs, ) -> Result { - Ok(Self::new( - ExternalProgramPath::resolve_program_path(program_name)?, + Ok(Self::with_resolved_program_path( + resolve_program_path( + program_name, + T::default_program_name(), + T::program_path_env_var_name().as_ref().map(AsRef::as_ref), + )?, additional_args, )) } @@ -600,7 +604,10 @@ impl ToArgs for ExternalCommandArgs { run_even_if_cached, ref additional_args, } = *self; - program_path.to_args(args); + args.write_arg(format_args!( + "--{}={program_path}", + T::program_path_arg_name() + )); if run_even_if_cached { args.write_arg(format_args!("--{}", T::run_even_if_cached_arg_name())); } @@ -619,11 +626,13 @@ struct ExternalCommandJobParams { impl ExternalCommandJobParams { fn new(job: &ExternalCommandJob) -> Self { let output_paths = T::output_paths(job); - let mut command_line = ArgsWriter(vec![job.program_path]); - T::command_line_args(job, &mut command_line); Self { command_params: CommandParams { - command_line: Intern::intern_owned(command_line.0), + command_line: Interned::from_iter( + [job.program_path] + .into_iter() + .chain(T::command_line_args(job).iter().copied()), + ), current_dir: T::current_dir(job), }, inputs: T::inputs(job), @@ -749,184 +758,33 @@ impl ExternalCommandJob { } } -#[derive(Copy, Clone, PartialEq, Eq, Hash)] -pub struct ExternalProgramPath { - program_path: Interned, - _phantom: PhantomData, -} - -impl ExternalProgramPath { - pub fn with_resolved_program_path(program_path: Interned) -> Self { - Self { - program_path, - _phantom: PhantomData, - } +pub trait ExternalCommand: 'static + Send + Sync + Hash + Eq + fmt::Debug + Sized + Clone { + type AdditionalArgs: ToArgs; + type AdditionalJobData: 'static + + Send + + Sync + + Hash + + Eq + + fmt::Debug + + Serialize + + DeserializeOwned; + type Dependencies: JobDependencies; + fn dependencies() -> Self::Dependencies; + fn args_to_jobs( + args: JobArgsAndDependencies>, + params: &JobParams, + ) -> eyre::Result<( + Self::AdditionalJobData, + ::JobsAndKinds, + )>; + fn inputs(job: &ExternalCommandJob) -> Interned<[JobItemName]>; + fn output_paths(job: &ExternalCommandJob) -> Interned<[Interned]>; + fn command_line_args(job: &ExternalCommandJob) -> Interned<[Interned]>; + fn current_dir(job: &ExternalCommandJob) -> Option>; + fn job_kind_name() -> Interned; + fn args_group_id() -> clap::Id { + Interned::into_inner(Self::job_kind_name()).into() } - pub fn resolve_program_path( - program_name: Option<&OsStr>, - ) -> Result { - let ExternalProgram { - default_program_name, - program_path_arg_name: _, - program_path_arg_value_name: _, - program_path_env_var_name, - } = ExternalProgram::new::(); - Ok(Self { - program_path: resolve_program_path( - program_name, - default_program_name, - program_path_env_var_name.as_ref().map(OsStr::new), - )?, - _phantom: PhantomData, - }) - } - pub fn program_path(&self) -> Interned { - self.program_path - } -} - -impl fmt::Debug for ExternalProgramPath { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let Self { - program_path, - _phantom: _, - } = self; - write!(f, "ExternalProgramPath<{}>", std::any::type_name::())?; - f.debug_tuple("").field(program_path).finish() - } -} - -impl clap::FromArgMatches for ExternalProgramPath { - fn from_arg_matches(matches: &clap::ArgMatches) -> Result { - let id = Interned::into_inner(ExternalProgram::new::().program_path_arg_name); - // don't remove argument so later instances of Self can use it too - let program_path = *matches.get_one(id).expect("arg should always be present"); - Ok(Self { - program_path, - _phantom: PhantomData, - }) - } - - fn update_from_arg_matches(&mut self, matches: &clap::ArgMatches) -> Result<(), clap::Error> { - *self = Self::from_arg_matches(matches)?; - Ok(()) - } -} - -impl clap::Args for ExternalProgramPath { - fn augment_args(cmd: clap::Command) -> clap::Command { - let external_program @ ExternalProgram { - default_program_name, - program_path_arg_name, - program_path_arg_value_name, - program_path_env_var_name, - } = ExternalProgram::new::(); - let arg = cmd - .get_arguments() - .find(|arg| *arg.get_id().as_str() == *program_path_arg_name); - if let Some(arg) = arg { - // don't insert duplicate arguments. - // check that the previous argument actually matches this argument: - assert!(!arg.is_required_set()); - assert!(matches!(arg.get_action(), clap::ArgAction::Set)); - assert_eq!(arg.get_long(), Some(&*program_path_arg_name)); - assert_eq!( - arg.get_value_names(), - Some(&[clap::builder::Str::from(program_path_arg_value_name)][..]) - ); - assert_eq!( - arg.get_env(), - program_path_env_var_name.as_ref().map(OsStr::new) - ); - assert_eq!( - arg.get_default_values(), - &[OsStr::new(&default_program_name)] - ); - assert_eq!(arg.get_value_hint(), clap::ValueHint::CommandName); - cmd - } else { - cmd.arg( - clap::Arg::new(Interned::into_inner(program_path_arg_name)) - .required(false) - .value_parser(ExternalProgramPathValueParser(external_program)) - .action(clap::ArgAction::Set) - .long(program_path_arg_name) - .value_name(program_path_arg_value_name) - .env(program_path_env_var_name.map(Interned::into_inner)) - .default_value(default_program_name) - .value_hint(clap::ValueHint::CommandName), - ) - } - } - - fn augment_args_for_update(cmd: clap::Command) -> clap::Command { - Self::augment_args(cmd) - } -} - -impl ToArgs for ExternalProgramPath { - fn to_args(&self, args: &mut (impl WriteArgs + ?Sized)) { - let ExternalProgram { - program_path_arg_name, - .. - } = ExternalProgram::new::(); - let Self { - program_path, - _phantom: _, - } = self; - if args.get_long_option_eq(program_path_arg_name) != Some(&**program_path) { - args.write_arg(format_args!("--{program_path_arg_name}={program_path}")); - } - } -} - -#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] -#[non_exhaustive] -pub struct ExternalProgram { - default_program_name: Interned, - program_path_arg_name: Interned, - program_path_arg_value_name: Interned, - program_path_env_var_name: Option>, -} - -impl ExternalProgram { - pub fn new() -> Self { - Self { - default_program_name: T::default_program_name(), - program_path_arg_name: T::program_path_arg_name(), - program_path_arg_value_name: T::program_path_arg_value_name(), - program_path_env_var_name: T::program_path_env_var_name(), - } - } - pub fn default_program_name(&self) -> Interned { - self.default_program_name - } - pub fn program_path_arg_name(&self) -> Interned { - self.program_path_arg_name - } - pub fn program_path_arg_value_name(&self) -> Interned { - self.program_path_arg_value_name - } - pub fn program_path_env_var_name(&self) -> Option> { - self.program_path_env_var_name - } -} - -impl From for ExternalProgram { - fn from(_value: T) -> Self { - Self::new::() - } -} - -impl From for Interned { - fn from(_value: T) -> Self { - ExternalProgram::new::().intern_sized() - } -} - -pub trait ExternalProgramTrait: - 'static + Send + Sync + Hash + Ord + fmt::Debug + Default + Copy -{ fn program_path_arg_name() -> Interned { Self::default_program_name() } @@ -941,36 +799,6 @@ pub trait ExternalProgramTrait: .replace('-', "_"), )) } -} - -pub trait ExternalCommand: 'static + Send + Sync + Hash + Eq + fmt::Debug + Sized + Clone { - type AdditionalArgs: ToArgs; - type AdditionalJobData: 'static - + Send - + Sync - + Hash - + Eq - + fmt::Debug - + Serialize - + DeserializeOwned; - type Dependencies: JobDependencies; - type ExternalProgram: ExternalProgramTrait; - fn dependencies() -> Self::Dependencies; - fn args_to_jobs( - args: JobArgsAndDependencies>, - params: &JobParams, - ) -> eyre::Result<( - Self::AdditionalJobData, - ::JobsAndKinds, - )>; - fn inputs(job: &ExternalCommandJob) -> Interned<[JobItemName]>; - fn output_paths(job: &ExternalCommandJob) -> Interned<[Interned]>; - fn command_line_args(job: &ExternalCommandJob, args: &mut W); - fn current_dir(job: &ExternalCommandJob) -> Option>; - fn job_kind_name() -> Interned; - fn args_group_id() -> clap::Id { - Interned::into_inner(Self::job_kind_name()).into() - } fn run_even_if_cached_arg_name() -> Interned { Intern::intern_owned(format!("{}-run-even-if-cached", Self::job_kind_name())) } @@ -996,11 +824,7 @@ impl JobKind for ExternalCommandJobKind { kind, args: ExternalCommandArgs { - program_path: - ExternalProgramPath { - program_path, - _phantom: _, - }, + program_path, run_even_if_cached, additional_args: _, }, @@ -1089,8 +913,4 @@ impl JobKind for ExternalCommandJobKind { fn subcommand_hidden(self) -> bool { T::subcommand_hidden() } - - fn external_program(self) -> Option> { - Some(ExternalProgram::new::().intern_sized()) - } } diff --git a/crates/fayalite/src/build/firrtl.rs b/crates/fayalite/src/build/firrtl.rs index 62657f8d..5dc4106e 100644 --- a/crates/fayalite/src/build/firrtl.rs +++ b/crates/fayalite/src/build/firrtl.rs @@ -3,9 +3,8 @@ use crate::{ build::{ - BaseJob, BaseJobKind, CommandParams, DynJobKind, JobAndDependencies, - JobArgsAndDependencies, JobItem, JobItemName, JobKind, JobKindAndDependencies, JobParams, - ToArgs, WriteArgs, + BaseJob, BaseJobKind, CommandParams, JobAndDependencies, JobArgsAndDependencies, JobItem, + JobItemName, JobKind, JobKindAndDependencies, JobParams, ToArgs, WriteArgs, }, firrtl::{ExportOptions, FileBackend}, intern::{Intern, Interned}, @@ -119,7 +118,3 @@ impl JobKind for FirrtlJobKind { }]) } } - -pub(crate) fn built_in_job_kinds() -> impl IntoIterator { - [DynJobKind::new(FirrtlJobKind)] -} diff --git a/crates/fayalite/src/build/formal.rs b/crates/fayalite/src/build/formal.rs index a289c811..366ce831 100644 --- a/crates/fayalite/src/build/formal.rs +++ b/crates/fayalite/src/build/formal.rs @@ -3,21 +3,18 @@ use crate::{ build::{ - CommandParams, DynJobKind, GetBaseJob, JobAndDependencies, JobArgsAndDependencies, - JobDependencies, JobItem, JobItemName, JobKind, JobKindAndDependencies, JobParams, ToArgs, - WriteArgs, - external::{ - ExternalCommand, ExternalCommandJob, ExternalCommandJobKind, ExternalProgramTrait, - }, + CommandParams, GetBaseJob, JobAndDependencies, JobArgsAndDependencies, JobDependencies, + JobItem, JobItemName, JobKind, JobKindAndDependencies, JobParams, ToArgs, WriteArgs, + external::{ExternalCommand, ExternalCommandJob, ExternalCommandJobKind}, interned_known_utf8_method, - verilog::{VerilogDialect, VerilogJob, VerilogJobKind}, + verilog::{VerilogDialect, VerilogJobKind}, }, intern::{Intern, Interned}, module::NameId, util::job_server::AcquiredJob, }; use clap::{Args, ValueEnum}; -use eyre::Context; +use eyre::{Context, eyre}; use serde::{Deserialize, Serialize}; use std::fmt; @@ -170,12 +167,28 @@ impl WriteSbyFileJob { \n\ [script]\n", )?; - let all_verilog_files = - match VerilogJob::all_verilog_files(*main_verilog_file, additional_files) { + for verilog_file in [main_verilog_file].into_iter().chain(additional_files) { + if !(verilog_file.ends_with(".v") || verilog_file.ends_with(".sv")) { + continue; + } + let verilog_file = match std::path::absolute(verilog_file) + .and_then(|v| { + v.into_os_string().into_string().map_err(|_| { + std::io::Error::new(std::io::ErrorKind::Other, "path is not valid UTF-8") + }) + }) + .wrap_err_with(|| format!("converting {verilog_file:?} to an absolute path failed")) + { Ok(v) => v, Err(e) => return Ok(Err(e)), }; - for verilog_file in all_verilog_files { + if verilog_file.contains(|ch: char| { + (ch != ' ' && ch != '\t' && ch.is_ascii_whitespace()) || ch == '"' + }) { + return Ok(Err(eyre!( + "verilog file path contains characters that aren't permitted" + ))); + } writeln!(output, "read_verilog -sv -formal \"{verilog_file}\"")?; } let circuit_name = crate::firrtl::get_circuit_name(main_module_name_id); @@ -262,10 +275,15 @@ impl JobKind for WriteSbyFileJobKind { _acquired_job: &mut AcquiredJob, ) -> eyre::Result> { assert!(inputs.iter().map(JobItem::name).eq(self.inputs(job))); - let [additional_files] = inputs else { + let [ + JobItem::DynamicPaths { + paths: additional_files, + .. + }, + ] = inputs + else { unreachable!(); }; - let additional_files = VerilogJob::unwrap_additional_files(additional_files); let mut contents = String::new(); match job.write_sby( &mut contents, @@ -321,15 +339,6 @@ impl fmt::Debug for Formal { } } -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Default)] -pub struct Symbiyosys; - -impl ExternalProgramTrait for Symbiyosys { - fn default_program_name() -> Interned { - "sby".intern() - } -} - #[derive(Clone, Hash, PartialEq, Eq, Debug, Args)] pub struct FormalAdditionalArgs {} @@ -343,7 +352,6 @@ impl ExternalCommand for Formal { type AdditionalArgs = FormalAdditionalArgs; type AdditionalJobData = Formal; type Dependencies = JobKindAndDependencies; - type ExternalProgram = Symbiyosys; fn dependencies() -> Self::Dependencies { Default::default() @@ -386,11 +394,15 @@ impl ExternalCommand for Formal { Interned::default() } - fn command_line_args(job: &ExternalCommandJob, args: &mut W) { - // args.write_str_arg("-j1"); // sby seems not to respect job count in parallel mode - args.write_str_arg("-f"); - args.write_interned_arg(job.additional_job_data().sby_file_name); - args.write_interned_args(job.additional_job_data().write_sby_file.sby_extra_args()); + fn command_line_args(job: &ExternalCommandJob) -> Interned<[Interned]> { + [ + // "-j1".intern(), // sby seems not to respect job count in parallel mode + "-f".intern(), + job.additional_job_data().sby_file_name, + ] + .into_iter() + .chain(job.additional_job_data().write_sby_file.sby_extra_args()) + .collect() } fn current_dir(job: &ExternalCommandJob) -> Option> { @@ -400,11 +412,8 @@ impl ExternalCommand for Formal { fn job_kind_name() -> Interned { "formal".intern() } -} -pub(crate) fn built_in_job_kinds() -> impl IntoIterator { - [ - DynJobKind::new(WriteSbyFileJobKind), - DynJobKind::new(ExternalCommandJobKind::::new()), - ] + fn default_program_name() -> Interned { + "sby".intern() + } } diff --git a/crates/fayalite/src/build/registry.rs b/crates/fayalite/src/build/registry.rs index ccb401fc..93d06f57 100644 --- a/crates/fayalite/src/build/registry.rs +++ b/crates/fayalite/src/build/registry.rs @@ -2,7 +2,7 @@ // See Notices.txt for copyright information use crate::{ - build::{DynJobKind, JobKind, built_in_job_kinds}, + build::{BUILT_IN_JOB_KINDS, DynJobKind, JobKind}, intern::Interned, }; use std::{ @@ -164,8 +164,8 @@ impl Default for JobKindRegistry { let mut retval = Self { job_kinds: BTreeMap::new(), }; - for job_kind in built_in_job_kinds() { - Self::register(&mut retval, job_kind); + for job_kind in BUILT_IN_JOB_KINDS { + Self::register(&mut retval, job_kind()); } retval } diff --git a/crates/fayalite/src/build/vendor.rs b/crates/fayalite/src/build/vendor.rs deleted file mode 100644 index 56297cf9..00000000 --- a/crates/fayalite/src/build/vendor.rs +++ /dev/null @@ -1,8 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// See Notices.txt for copyright information - -pub mod xilinx; - -pub(crate) fn built_in_job_kinds() -> impl IntoIterator { - xilinx::built_in_job_kinds() -} diff --git a/crates/fayalite/src/build/vendor/xilinx.rs b/crates/fayalite/src/build/vendor/xilinx.rs deleted file mode 100644 index 049c49cb..00000000 --- a/crates/fayalite/src/build/vendor/xilinx.rs +++ /dev/null @@ -1,8 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// See Notices.txt for copyright information - -pub mod yosys_nextpnr_prjxray; - -pub(crate) fn built_in_job_kinds() -> impl IntoIterator { - yosys_nextpnr_prjxray::built_in_job_kinds() -} diff --git a/crates/fayalite/src/build/vendor/xilinx/yosys_nextpnr_prjxray.rs b/crates/fayalite/src/build/vendor/xilinx/yosys_nextpnr_prjxray.rs deleted file mode 100644 index 3a6ba557..00000000 --- a/crates/fayalite/src/build/vendor/xilinx/yosys_nextpnr_prjxray.rs +++ /dev/null @@ -1,669 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// See Notices.txt for copyright information - -use crate::{ - build::{ - CommandParams, DynJobKind, GetBaseJob, JobAndDependencies, JobArgsAndDependencies, - JobDependencies, JobItem, JobItemName, JobKind, JobKindAndDependencies, ToArgs, WriteArgs, - external::{ - ExternalCommand, ExternalCommandJob, ExternalCommandJobKind, ExternalProgramTrait, - }, - interned_known_utf8_method, interned_known_utf8_path_buf_method, - verilog::{VerilogDialect, VerilogJob, VerilogJobKind}, - }, - intern::{Intern, Interned}, - module::NameId, - prelude::JobParams, - util::job_server::AcquiredJob, -}; -use clap::ValueEnum; -use eyre::Context; -use serde::{Deserialize, Serialize}; -use std::fmt; - -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash, Default)] -pub struct YosysNextpnrXrayWriteYsFileJobKind; - -#[derive(Clone, PartialEq, Eq, Hash, Debug, clap::Args)] -pub struct YosysNextpnrXrayWriteYsFileArgs {} - -impl ToArgs for YosysNextpnrXrayWriteYsFileArgs { - fn to_args(&self, _args: &mut (impl WriteArgs + ?Sized)) { - let Self {} = self; - } -} - -#[derive(Clone, PartialEq, Eq, Hash, Debug, Serialize, Deserialize)] -pub struct YosysNextpnrXrayWriteYsFile { - main_verilog_file: Interned, - ys_file: Interned, - json_file: Interned, - json_file_name: Interned, -} - -impl YosysNextpnrXrayWriteYsFile { - pub fn main_verilog_file(&self) -> Interned { - self.main_verilog_file - } - pub fn ys_file(&self) -> Interned { - self.ys_file - } - pub fn json_file(&self) -> Interned { - self.json_file - } - pub fn json_file_name(&self) -> Interned { - self.json_file_name - } - fn write_ys( - &self, - output: &mut W, - additional_files: &[Interned], - main_module_name_id: NameId, - ) -> Result, fmt::Error> { - let Self { - main_verilog_file, - ys_file: _, - json_file: _, - json_file_name, - } = self; - let all_verilog_files = - match VerilogJob::all_verilog_files(*main_verilog_file, additional_files) { - Ok(v) => v, - Err(e) => return Ok(Err(e)), - }; - for verilog_file in all_verilog_files { - writeln!(output, "read_verilog -sv \"{verilog_file}\"")?; - } - let circuit_name = crate::firrtl::get_circuit_name(main_module_name_id); - writeln!( - output, - "synth_xilinx -flatten -abc9 -nobram -arch xc7 -top {circuit_name}" - )?; - writeln!(output, "write_json \"{json_file_name}\"")?; - Ok(Ok(())) - } -} - -impl JobKind for YosysNextpnrXrayWriteYsFileJobKind { - type Args = YosysNextpnrXrayWriteYsFileArgs; - type Job = YosysNextpnrXrayWriteYsFile; - type Dependencies = JobKindAndDependencies; - - fn dependencies(self) -> Self::Dependencies { - Default::default() - } - - fn args_to_jobs( - mut args: JobArgsAndDependencies, - params: &JobParams, - ) -> eyre::Result> { - args.dependencies - .dependencies - .args - .args - .additional_args - .verilog_dialect - .get_or_insert(VerilogDialect::Yosys); - args.args_to_jobs_simple(params, |_kind, args, dependencies| { - let YosysNextpnrXrayWriteYsFileArgs {} = args; - let json_file = dependencies.base_job().file_with_ext("json"); - Ok(YosysNextpnrXrayWriteYsFile { - main_verilog_file: dependencies.job.job.main_verilog_file(), - ys_file: dependencies.base_job().file_with_ext("ys"), - json_file, - json_file_name: interned_known_utf8_method(json_file, |v| { - v.file_name().expect("known to have file name") - }), - }) - }) - } - - fn inputs(self, _job: &Self::Job) -> Interned<[JobItemName]> { - [JobItemName::DynamicPaths { - source_job_name: VerilogJobKind.name(), - }][..] - .intern() - } - - fn outputs(self, job: &Self::Job) -> Interned<[JobItemName]> { - [JobItemName::Path { path: job.ys_file }][..].intern() - } - - fn name(self) -> Interned { - "yosys-nextpnr-xray-write-ys-file".intern() - } - - fn external_command_params(self, _job: &Self::Job) -> Option { - None - } - - fn run( - self, - job: &Self::Job, - inputs: &[JobItem], - params: &JobParams, - _acquired_job: &mut AcquiredJob, - ) -> eyre::Result> { - assert!(inputs.iter().map(JobItem::name).eq(self.inputs(job))); - let [additional_files] = inputs else { - unreachable!(); - }; - let additional_files = VerilogJob::unwrap_additional_files(additional_files); - let mut contents = String::new(); - match job.write_ys( - &mut contents, - additional_files, - params.main_module().name_id(), - ) { - Ok(result) => result?, - Err(fmt::Error) => unreachable!("writing to String can't fail"), - } - std::fs::write(job.ys_file, contents) - .wrap_err_with(|| format!("writing {} failed", job.ys_file))?; - Ok(vec![JobItem::Path { path: job.ys_file }]) - } - - fn subcommand_hidden(self) -> bool { - true - } -} - -#[derive(Clone, PartialEq, Eq, Hash, Debug, clap::Args)] -pub struct YosysNextpnrXraySynthArgs {} - -impl ToArgs for YosysNextpnrXraySynthArgs { - fn to_args(&self, _args: &mut (impl WriteArgs + ?Sized)) { - let Self {} = self; - } -} - -#[derive(Clone, PartialEq, Eq, Hash, Deserialize, Serialize)] -pub struct YosysNextpnrXraySynth { - #[serde(flatten)] - write_ys_file: YosysNextpnrXrayWriteYsFile, - ys_file_name: Interned, -} - -impl fmt::Debug for YosysNextpnrXraySynth { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let Self { - write_ys_file: - YosysNextpnrXrayWriteYsFile { - main_verilog_file, - ys_file, - json_file, - json_file_name, - }, - ys_file_name, - } = self; - f.debug_struct("YosysNextpnrXraySynth") - .field("main_verilog_file", main_verilog_file) - .field("ys_file", ys_file) - .field("ys_file_name", ys_file_name) - .field("json_file", json_file) - .field("json_file_name", json_file_name) - .finish() - } -} - -impl YosysNextpnrXraySynth { - pub fn main_verilog_file(&self) -> Interned { - self.write_ys_file.main_verilog_file() - } - pub fn ys_file(&self) -> Interned { - self.write_ys_file.ys_file() - } - pub fn ys_file_name(&self) -> Interned { - self.ys_file_name - } - pub fn json_file(&self) -> Interned { - self.write_ys_file.json_file() - } - pub fn json_file_name(&self) -> Interned { - self.write_ys_file.json_file_name() - } -} - -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Default)] -pub struct Yosys; - -impl ExternalProgramTrait for Yosys { - fn default_program_name() -> Interned { - "yosys".intern() - } -} - -impl ExternalCommand for YosysNextpnrXraySynth { - type AdditionalArgs = YosysNextpnrXraySynthArgs; - type AdditionalJobData = Self; - type Dependencies = JobKindAndDependencies; - type ExternalProgram = Yosys; - - fn dependencies() -> Self::Dependencies { - Default::default() - } - - fn args_to_jobs( - args: JobArgsAndDependencies>, - params: &JobParams, - ) -> eyre::Result<( - Self::AdditionalJobData, - ::JobsAndKinds, - )> { - args.args_to_jobs_external_simple(params, |args, dependencies| { - let YosysNextpnrXraySynthArgs {} = args.additional_args; - Ok(Self { - write_ys_file: dependencies.job.job.clone(), - ys_file_name: interned_known_utf8_method(dependencies.job.job.ys_file(), |v| { - v.file_name().expect("known to have file name") - }), - }) - }) - } - - fn inputs(job: &ExternalCommandJob) -> Interned<[JobItemName]> { - [ - JobItemName::Path { - path: job.additional_job_data().ys_file(), - }, - JobItemName::Path { - path: job.additional_job_data().main_verilog_file(), - }, - JobItemName::DynamicPaths { - source_job_name: VerilogJobKind.name(), - }, - ][..] - .intern() - } - - fn output_paths(job: &ExternalCommandJob) -> Interned<[Interned]> { - [job.additional_job_data().json_file()][..].intern() - } - - fn command_line_args(job: &ExternalCommandJob, args: &mut W) { - args.write_str_arg("-s"); - args.write_interned_arg(job.additional_job_data().ys_file_name()); - } - - fn current_dir(job: &ExternalCommandJob) -> Option> { - Some(job.output_dir()) - } - - fn job_kind_name() -> Interned { - "yosys-nextpnr-xray-synth".intern() - } - - fn subcommand_hidden() -> bool { - true - } -} - -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash, Default)] -pub struct YosysNextpnrXrayWriteXdcFileJobKind; - -#[derive(Clone, PartialEq, Eq, Hash, Debug, clap::Args)] -pub struct YosysNextpnrXrayWriteXdcFileArgs {} - -impl ToArgs for YosysNextpnrXrayWriteXdcFileArgs { - fn to_args(&self, _args: &mut (impl WriteArgs + ?Sized)) { - let Self {} = self; - } -} - -#[derive(Clone, PartialEq, Eq, Hash, Debug, Serialize, Deserialize)] -pub struct YosysNextpnrXrayWriteXdcFile { - output_dir: Interned, - xdc_file: Interned, -} - -impl JobKind for YosysNextpnrXrayWriteXdcFileJobKind { - type Args = YosysNextpnrXrayWriteXdcFileArgs; - type Job = YosysNextpnrXrayWriteXdcFile; - type Dependencies = JobKindAndDependencies>; - - fn dependencies(self) -> Self::Dependencies { - Default::default() - } - - fn args_to_jobs( - args: JobArgsAndDependencies, - params: &JobParams, - ) -> eyre::Result> { - args.args_to_jobs_simple(params, |_kind, args, dependencies| { - let YosysNextpnrXrayWriteXdcFileArgs {} = args; - Ok(YosysNextpnrXrayWriteXdcFile { - output_dir: dependencies.base_job().output_dir(), - xdc_file: dependencies.base_job().file_with_ext("xdc"), - }) - }) - } - - fn inputs(self, job: &Self::Job) -> Interned<[JobItemName]> { - [JobItemName::Path { - path: job.output_dir, - }][..] - .intern() - } - - fn outputs(self, job: &Self::Job) -> Interned<[JobItemName]> { - [JobItemName::Path { path: job.xdc_file }][..].intern() - } - - fn name(self) -> Interned { - "yosys-nextpnr-xray-write-xdc-file".intern() - } - - fn external_command_params(self, _job: &Self::Job) -> Option { - None - } - - fn run( - self, - job: &Self::Job, - inputs: &[JobItem], - params: &JobParams, - acquired_job: &mut AcquiredJob, - ) -> eyre::Result> { - todo!() - } - - fn subcommand_hidden(self) -> bool { - true - } -} - -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Default)] -pub struct NextpnrXilinx; - -impl ExternalProgramTrait for NextpnrXilinx { - fn default_program_name() -> Interned { - "nextpnr-xilinx".intern() - } -} - -macro_rules! make_device_enum { - ($vis:vis enum $Device:ident { - $( - #[ - name = $name:literal, - xray_part = $xray_part:literal, - xray_device = $xray_device:literal, - xray_family = $xray_family:literal, - ] - $variant:ident, - )* - }) => { - #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, ValueEnum)] - $vis enum $Device { - $( - #[value(name = $name, alias = $xray_part)] - $variant, - )* - } - - impl $Device { - $vis fn as_str(self) -> &'static str { - match self { - $(Self::$variant => $name,)* - } - } - $vis fn xray_part(self) -> &'static str { - match self { - $(Self::$variant => $xray_part,)* - } - } - $vis fn xray_device(self) -> &'static str { - match self { - $(Self::$variant => $xray_device,)* - } - } - $vis fn xray_family(self) -> &'static str { - match self { - $(Self::$variant => $xray_family,)* - } - } - } - - struct DeviceVisitor; - - impl<'de> serde::de::Visitor<'de> for DeviceVisitor { - type Value = $Device; - - fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str("a Xilinx device string") - } - - fn visit_str(self, v: &str) -> Result - where - E: serde::de::Error, - { - match $Device::from_str(v, false) { - Ok(v) => Ok(v), - Err(_) => Err(E::invalid_value(serde::de::Unexpected::Str(v), &self)), - } - } - - fn visit_bytes(self, v: &[u8]) -> Result - where - E: serde::de::Error, - { - match str::from_utf8(v).ok().and_then(|v| $Device::from_str(v, false).ok()) { - Some(v) => Ok(v), - None => Err(E::invalid_value(serde::de::Unexpected::Bytes(v), &self)), - } - } - } - - impl<'de> Deserialize<'de> for $Device { - fn deserialize(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - deserializer.deserialize_string(DeviceVisitor) - } - } - - impl Serialize for $Device { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - self.as_str().serialize(serializer) - } - } - }; -} - -make_device_enum! { - pub enum Device { - #[ - name = "xc7a35ticsg324-1L", - xray_part = "xc7a35tcsg324-1", - xray_device = "xc7a35t", - xray_family = "artix7", - ] - Xc7a35ticsg324_1l, - #[ - name = "xc7a100ticsg324-1L", - xray_part = "xc7a100tcsg324-1", - xray_device = "xc7a100t", - xray_family = "artix7", - ] - Xc7a100ticsg324_1l, - } -} - -impl fmt::Display for Device { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str(self.as_str()) - } -} - -#[derive(Clone, PartialEq, Eq, Hash, Debug, clap::Args)] -pub struct YosysNextpnrXrayRunNextpnrArgs { - #[arg(long, env = "CHIPDB_DIR", value_hint = clap::ValueHint::DirPath)] - pub nextpnr_xilinx_chipdb_dir: String, - #[arg(long)] - pub device: Device, - #[arg(long, default_value_t = 0)] - pub nextpnr_xilinx_seed: i32, -} - -impl ToArgs for YosysNextpnrXrayRunNextpnrArgs { - fn to_args(&self, args: &mut (impl WriteArgs + ?Sized)) { - let Self { - nextpnr_xilinx_chipdb_dir, - device, - nextpnr_xilinx_seed, - } = self; - args.write_args([ - format_args!("--nextpnr-xilinx-chipdb-dir={nextpnr_xilinx_chipdb_dir}"), - format_args!("--device={device}"), - format_args!("--nextpnr-xilinx-seed={nextpnr_xilinx_seed}"), - ]); - } -} - -#[derive(Clone, PartialEq, Eq, Hash, Debug, Serialize, Deserialize)] -pub struct YosysNextpnrXrayRunNextpnr { - nextpnr_xilinx_chipdb_dir: Interned, - device: Device, - nextpnr_xilinx_seed: i32, - xdc_file: Interned, - xdc_file_name: Interned, - json_file: Interned, - json_file_name: Interned, - routed_json_file: Interned, - routed_json_file_name: Interned, - fasm_file: Interned, - fasm_file_name: Interned, -} - -impl YosysNextpnrXrayRunNextpnr { - fn chipdb_file(&self) -> Interned { - interned_known_utf8_path_buf_method(self.nextpnr_xilinx_chipdb_dir, |chipdb_dir| { - let mut retval = chipdb_dir.join(self.device.xray_device()); - retval.set_extension("bin"); - retval - }) - } -} - -impl ExternalCommand for YosysNextpnrXrayRunNextpnr { - type AdditionalArgs = YosysNextpnrXrayRunNextpnrArgs; - type AdditionalJobData = Self; - type Dependencies = JobKindAndDependencies; - type ExternalProgram = NextpnrXilinx; - - fn dependencies() -> Self::Dependencies { - Default::default() - } - - fn args_to_jobs( - args: JobArgsAndDependencies>, - params: &JobParams, - ) -> eyre::Result<( - Self::AdditionalJobData, - ::JobsAndKinds, - )> { - args.args_to_jobs_external_simple(params, |args, dependencies| { - let YosysNextpnrXrayRunNextpnrArgs { - nextpnr_xilinx_chipdb_dir, - device, - nextpnr_xilinx_seed, - } = args.additional_args; - let xdc_file = dependencies.job.job.xdc_file; - let routed_json_file = dependencies.base_job().file_with_ext("routed.json"); - let fasm_file = dependencies.base_job().file_with_ext("fasm"); - Ok(Self { - nextpnr_xilinx_chipdb_dir: str::intern_owned(nextpnr_xilinx_chipdb_dir), - device, - nextpnr_xilinx_seed, - xdc_file, - xdc_file_name: interned_known_utf8_method(xdc_file, |v| { - v.file_name().expect("known to have file name") - }), - json_file: dependencies - .dependencies - .job - .job - .additional_job_data() - .json_file(), - json_file_name: dependencies - .dependencies - .job - .job - .additional_job_data() - .json_file_name(), - routed_json_file, - routed_json_file_name: interned_known_utf8_method(routed_json_file, |v| { - v.file_name().expect("known to have file name") - }), - fasm_file, - fasm_file_name: interned_known_utf8_method(fasm_file, |v| { - v.file_name().expect("known to have file name") - }), - }) - }) - } - - fn inputs(job: &ExternalCommandJob) -> Interned<[JobItemName]> { - [ - JobItemName::Path { - path: job.additional_job_data().json_file, - }, - JobItemName::Path { - path: job.additional_job_data().xdc_file, - }, - ][..] - .intern() - } - - fn output_paths(job: &ExternalCommandJob) -> Interned<[Interned]> { - [ - job.additional_job_data().routed_json_file, - job.additional_job_data().fasm_file, - ][..] - .intern() - } - - fn command_line_args(job: &ExternalCommandJob, args: &mut W) { - let job_data @ YosysNextpnrXrayRunNextpnr { - nextpnr_xilinx_seed, - xdc_file_name, - json_file_name, - routed_json_file_name, - fasm_file_name, - .. - } = job.additional_job_data(); - args.write_args([ - format_args!("--chipdb={}", job_data.chipdb_file()), - format_args!("--xdc={xdc_file_name}"), - format_args!("--json={json_file_name}"), - format_args!("--write={routed_json_file_name}"), - format_args!("--fasm={fasm_file_name}"), - format_args!("--seed={nextpnr_xilinx_seed}"), - ]); - } - - fn current_dir(job: &ExternalCommandJob) -> Option> { - Some(job.output_dir()) - } - - fn job_kind_name() -> Interned { - "yosys-nextpnr-xray-run-nextpnr".intern() - } - - fn subcommand_hidden() -> bool { - true - } -} - -pub(crate) fn built_in_job_kinds() -> impl IntoIterator { - [ - DynJobKind::new(YosysNextpnrXrayWriteYsFileJobKind), - DynJobKind::new(ExternalCommandJobKind::::new()), - DynJobKind::new(YosysNextpnrXrayWriteXdcFileJobKind), - DynJobKind::new(ExternalCommandJobKind::::new()), - ] -} diff --git a/crates/fayalite/src/build/verilog.rs b/crates/fayalite/src/build/verilog.rs index 39334f2c..219dda89 100644 --- a/crates/fayalite/src/build/verilog.rs +++ b/crates/fayalite/src/build/verilog.rs @@ -3,12 +3,9 @@ use crate::{ build::{ - CommandParams, DynJobKind, GetBaseJob, JobAndDependencies, JobArgsAndDependencies, - JobDependencies, JobItem, JobItemName, JobKind, JobKindAndDependencies, JobParams, ToArgs, - WriteArgs, - external::{ - ExternalCommand, ExternalCommandJob, ExternalCommandJobKind, ExternalProgramTrait, - }, + CommandParams, GetBaseJob, JobAndDependencies, JobArgsAndDependencies, JobDependencies, + JobItem, JobItemName, JobKind, JobKindAndDependencies, JobParams, ToArgs, WriteArgs, + external::{ExternalCommand, ExternalCommandJob, ExternalCommandJobKind}, firrtl::FirrtlJobKind, interned_known_utf8_method, interned_known_utf8_path_buf_method, }, @@ -16,7 +13,7 @@ use crate::{ util::job_server::AcquiredJob, }; use clap::Args; -use eyre::{Context, bail}; +use eyre::bail; use serde::{Deserialize, Serialize}; use std::{fmt, mem}; @@ -99,15 +96,6 @@ impl ToArgs for UnadjustedVerilogArgs { } } -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Default)] -pub struct Firtool; - -impl ExternalProgramTrait for Firtool { - fn default_program_name() -> Interned { - "firtool".intern() - } -} - #[derive(Clone, PartialEq, Eq, Hash, Debug, Deserialize, Serialize)] pub struct UnadjustedVerilog { firrtl_file: Interned, @@ -141,7 +129,6 @@ impl ExternalCommand for UnadjustedVerilog { type AdditionalArgs = UnadjustedVerilogArgs; type AdditionalJobData = UnadjustedVerilog; type Dependencies = JobKindAndDependencies; - type ExternalProgram = Firtool; fn dependencies() -> Self::Dependencies { Default::default() @@ -197,7 +184,7 @@ impl ExternalCommand for UnadjustedVerilog { [job.additional_job_data().unadjusted_verilog_file][..].intern() } - fn command_line_args(job: &ExternalCommandJob, args: &mut W) { + fn command_line_args(job: &ExternalCommandJob) -> Interned<[Interned]> { let UnadjustedVerilog { firrtl_file: _, firrtl_file_name, @@ -207,16 +194,26 @@ impl ExternalCommand for UnadjustedVerilog { verilog_dialect, verilog_debug, } = *job.additional_job_data(); - args.write_interned_arg(firrtl_file_name); - args.write_str_arg("-o"); - args.write_interned_arg(unadjusted_verilog_file_name); + let mut retval = vec![ + firrtl_file_name, + "-o".intern(), + unadjusted_verilog_file_name, + ]; if verilog_debug { - args.write_str_args(["-g", "--preserve-values=all"]); + retval.push("-g".intern()); + retval.push("--preserve-values=all".intern()); } if let Some(dialect) = verilog_dialect { - args.write_str_args(dialect.firtool_extra_args().iter().copied()); + retval.extend( + dialect + .firtool_extra_args() + .iter() + .copied() + .map(str::intern), + ); } - args.write_interned_args(firtool_extra_args); + retval.extend_from_slice(&firtool_extra_args); + Intern::intern_owned(retval) } fn current_dir(job: &ExternalCommandJob) -> Option> { @@ -227,6 +224,10 @@ impl ExternalCommand for UnadjustedVerilog { "unadjusted-verilog".intern() } + fn default_program_name() -> Interned { + "firtool".intern() + } + fn subcommand_hidden() -> bool { true } @@ -266,43 +267,6 @@ impl VerilogJob { pub fn main_verilog_file(&self) -> Interned { self.main_verilog_file } - #[track_caller] - pub fn unwrap_additional_files(additional_files: &JobItem) -> &[Interned] { - match additional_files { - JobItem::DynamicPaths { - paths, - source_job_name, - } if *source_job_name == VerilogJobKind.name() => paths, - v => panic!("expected VerilogJob's additional files JobItem: {v:?}"), - } - } - pub fn all_verilog_files( - main_verilog_file: Interned, - additional_files: &[Interned], - ) -> eyre::Result]>> { - let mut retval = Vec::with_capacity(additional_files.len().saturating_add(1)); - for verilog_file in [main_verilog_file].iter().chain(additional_files) { - if !(verilog_file.ends_with(".v") || verilog_file.ends_with(".sv")) { - continue; - } - let verilog_file = std::path::absolute(verilog_file) - .and_then(|v| { - v.into_os_string().into_string().map_err(|_| { - std::io::Error::new(std::io::ErrorKind::Other, "path is not valid UTF-8") - }) - }) - .wrap_err_with(|| { - format!("converting {verilog_file:?} to an absolute path failed") - })?; - if verilog_file.contains(|ch: char| { - (ch != ' ' && ch != '\t' && ch.is_ascii_whitespace()) || ch == '"' - }) { - bail!("verilog file path contains characters that aren't permitted"); - } - retval.push(str::intern_owned(verilog_file)); - } - Ok(Intern::intern_owned(retval)) - } } impl JobKind for VerilogJobKind { @@ -407,10 +371,3 @@ impl JobKind for VerilogJobKind { ]) } } - -pub(crate) fn built_in_job_kinds() -> impl IntoIterator { - [ - DynJobKind::new(ExternalCommandJobKind::::new()), - DynJobKind::new(VerilogJobKind), - ] -} diff --git a/crates/fayalite/src/module/transform/simplify_enums.rs b/crates/fayalite/src/module/transform/simplify_enums.rs index 0839881b..dd21e493 100644 --- a/crates/fayalite/src/module/transform/simplify_enums.rs +++ b/crates/fayalite/src/module/transform/simplify_enums.rs @@ -1,3 +1,5 @@ +use serde::{Deserialize, Serialize}; + // SPDX-License-Identifier: LGPL-3.0-or-later // See Notices.txt for copyright information use crate::{ @@ -22,7 +24,6 @@ use crate::{ wire::Wire, }; use core::fmt; -use serde::{Deserialize, Serialize}; #[derive(Debug)] pub enum SimplifyEnumsError { diff --git a/crates/fayalite/src/testing.rs b/crates/fayalite/src/testing.rs index 47c7cfa3..e7465bf8 100644 --- a/crates/fayalite/src/testing.rs +++ b/crates/fayalite/src/testing.rs @@ -125,7 +125,7 @@ fn make_assert_formal_args( let dependencies = JobArgsAndDependencies { args, dependencies }; let args = JobKindAndArgs { kind: ExternalCommandJobKind::new(), - args: ExternalCommandArgs::resolve_program_path( + args: ExternalCommandArgs::new( None, UnadjustedVerilogArgs { firtool_extra_args: vec![], @@ -153,7 +153,7 @@ fn make_assert_formal_args( let dependencies = JobArgsAndDependencies { args, dependencies }; let args = JobKindAndArgs { kind: ExternalCommandJobKind::new(), - args: ExternalCommandArgs::resolve_program_path(None, FormalAdditionalArgs {})?, + args: ExternalCommandArgs::new(None, FormalAdditionalArgs {})?, }; Ok(JobArgsAndDependencies { args, dependencies }) }