forked from libre-chip/fayalite
add beginnings of simple CLI
This commit is contained in:
parent
8080cc7b5c
commit
23a77368b3
4 changed files with 257 additions and 1 deletions
|
@ -21,6 +21,8 @@ num-traits = { workspace = true }
|
|||
fayalite-proc-macros = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
clap = { version = "4.5.9", features = ["derive"] }
|
||||
eyre = "0.6.12"
|
||||
|
||||
[dev-dependencies]
|
||||
trybuild = { workspace = true }
|
||||
|
@ -32,4 +34,4 @@ fayalite-visit-gen = { workspace = true }
|
|||
unstable-doc = []
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
features = ["unstable-doc"]
|
||||
features = ["unstable-doc"]
|
||||
|
|
116
crates/fayalite/src/cli.rs
Normal file
116
crates/fayalite/src/cli.rs
Normal file
|
@ -0,0 +1,116 @@
|
|||
use crate::{
|
||||
bundle::{BundleType, BundleValue, DynBundle},
|
||||
firrtl,
|
||||
intern::Interned,
|
||||
module::Module,
|
||||
};
|
||||
use clap::{Parser, Subcommand, ValueHint};
|
||||
use std::{path::PathBuf, process::exit};
|
||||
|
||||
#[derive(Subcommand)]
|
||||
enum CliCommand {
|
||||
/// Generate FIRRTL
|
||||
Firrtl {
|
||||
/// the directory to put the generated FIRRTL and associated files in
|
||||
#[arg(short, long, value_hint = ValueHint::DirPath)]
|
||||
output: PathBuf,
|
||||
/// the stem of the generated .fir file, e.g. to get foo.fir, pass --file-stem=foo
|
||||
#[arg(long)]
|
||||
file_stem: Option<String>,
|
||||
},
|
||||
}
|
||||
|
||||
/// a simple CLI
|
||||
///
|
||||
/// Use like:
|
||||
///
|
||||
/// ```no_run
|
||||
/// # use fayalite::{hdl_module, cli::Cli};
|
||||
/// # #[hdl_module]
|
||||
/// # fn my_module() {}
|
||||
/// fn main() {
|
||||
/// Cli::parse().run(my_module());
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// You can also use it with a larger [`clap`]-based CLI like so:
|
||||
///
|
||||
/// ```no_run
|
||||
/// # use fayalite::{hdl_module};
|
||||
/// # #[hdl_module]
|
||||
/// # fn my_module() {}
|
||||
///
|
||||
/// #[derive(clap::Subcommand)]
|
||||
/// pub enum Subcommand {
|
||||
/// #[command(flatten)]
|
||||
/// Fayalite(fayalite::cli::Cli),
|
||||
/// MySpecialCommand {
|
||||
/// #[arg]
|
||||
/// foo: bool,
|
||||
/// },
|
||||
/// }
|
||||
///
|
||||
/// #[derive(clap::Parser)]
|
||||
/// pub struct Cli {
|
||||
/// #[command(subcommand)]
|
||||
/// subcommand: Subcommand, // or just use fayalite::cli::Cli directly
|
||||
/// }
|
||||
/// fn main() {
|
||||
/// match Cli::parse().subcommand {
|
||||
/// Subcommand::Fayalite(v) => v.run(my_module()),
|
||||
/// Subcommand::MySpecialCommand { foo } => println!("special: foo={foo}"),
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
#[derive(Parser)]
|
||||
// clear things that would be crate-specific
|
||||
#[command(name = "Fayalite Simple CLI", about = None, long_about = None)]
|
||||
pub struct Cli {
|
||||
#[command(subcommand)]
|
||||
subcommand: CliCommand,
|
||||
}
|
||||
|
||||
impl clap::Subcommand for Cli {
|
||||
fn augment_subcommands(cmd: clap::Command) -> clap::Command {
|
||||
CliCommand::augment_subcommands(cmd)
|
||||
}
|
||||
|
||||
fn augment_subcommands_for_update(cmd: clap::Command) -> clap::Command {
|
||||
CliCommand::augment_subcommands_for_update(cmd)
|
||||
}
|
||||
|
||||
fn has_subcommand(name: &str) -> bool {
|
||||
CliCommand::has_subcommand(name)
|
||||
}
|
||||
}
|
||||
|
||||
impl Cli {
|
||||
/// forwards to [`clap::Parser::parse()`] so you don't have to import [`clap::Parser`]
|
||||
pub fn parse() -> Self {
|
||||
clap::Parser::parse()
|
||||
}
|
||||
fn run_impl(self, top_module: Module<DynBundle>) -> ! {
|
||||
match self.subcommand {
|
||||
CliCommand::Firrtl { output, file_stem } => {
|
||||
let result = firrtl::export(
|
||||
firrtl::FileBackend {
|
||||
dir_path: output,
|
||||
top_fir_file_stem: file_stem,
|
||||
},
|
||||
&top_module,
|
||||
);
|
||||
if let Err(e) = result {
|
||||
eprintln!("Error: {:?}", eyre::Report::new(e));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
exit(0)
|
||||
}
|
||||
pub fn run<T: BundleValue>(self, top_module: Interned<Module<T>>) -> !
|
||||
where
|
||||
T::Type: BundleType<Value = T>,
|
||||
{
|
||||
self.run_impl(top_module.canonical())
|
||||
}
|
||||
}
|
|
@ -27,6 +27,7 @@ pub mod _docs;
|
|||
pub mod annotations;
|
||||
pub mod array;
|
||||
pub mod bundle;
|
||||
pub mod cli;
|
||||
pub mod clock;
|
||||
pub mod enum_;
|
||||
pub mod expr;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue