Compare commits
	
		
			5 commits
		
	
	
		
			1809fccb45
			...
			a191ece9a5
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| a191ece9a5 | |||
| 23a77368b3 | |||
| 8080cc7b5c | |||
| bdfa18e11d | |||
| 8ca0cd56c4 | 
					 7 changed files with 381 additions and 2 deletions
				
			
		
							
								
								
									
										137
									
								
								Cargo.lock
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										137
									
								
								Cargo.lock
									
										
									
										generated
									
									
									
								
							| 
						 | 
					@ -20,6 +20,55 @@ version = "0.2.16"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5"
 | 
					checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "anstream"
 | 
				
			||||||
 | 
					version = "0.6.14"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "anstyle",
 | 
				
			||||||
 | 
					 "anstyle-parse",
 | 
				
			||||||
 | 
					 "anstyle-query",
 | 
				
			||||||
 | 
					 "anstyle-wincon",
 | 
				
			||||||
 | 
					 "colorchoice",
 | 
				
			||||||
 | 
					 "is_terminal_polyfill",
 | 
				
			||||||
 | 
					 "utf8parse",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "anstyle"
 | 
				
			||||||
 | 
					version = "1.0.7"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "anstyle-parse"
 | 
				
			||||||
 | 
					version = "0.2.4"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "utf8parse",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "anstyle-query"
 | 
				
			||||||
 | 
					version = "1.1.0"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "windows-sys",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "anstyle-wincon"
 | 
				
			||||||
 | 
					version = "3.0.3"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "anstyle",
 | 
				
			||||||
 | 
					 "windows-sys",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "autocfg"
 | 
					name = "autocfg"
 | 
				
			||||||
version = "1.1.0"
 | 
					version = "1.1.0"
 | 
				
			||||||
| 
						 | 
					@ -75,6 +124,52 @@ version = "1.0.0"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
 | 
					checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "clap"
 | 
				
			||||||
 | 
					version = "4.5.9"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "64acc1846d54c1fe936a78dc189c34e28d3f5afc348403f28ecf53660b9b8462"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "clap_builder",
 | 
				
			||||||
 | 
					 "clap_derive",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "clap_builder"
 | 
				
			||||||
 | 
					version = "4.5.9"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "6fb8393d67ba2e7bfaf28a23458e4e2b543cc73a99595511eb207fdb8aede942"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "anstream",
 | 
				
			||||||
 | 
					 "anstyle",
 | 
				
			||||||
 | 
					 "clap_lex",
 | 
				
			||||||
 | 
					 "strsim",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "clap_derive"
 | 
				
			||||||
 | 
					version = "4.5.8"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "2bac35c6dafb060fd4d275d9a4ffae97917c13a6327903a8be2153cd964f7085"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "heck",
 | 
				
			||||||
 | 
					 "proc-macro2",
 | 
				
			||||||
 | 
					 "quote",
 | 
				
			||||||
 | 
					 "syn",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "clap_lex"
 | 
				
			||||||
 | 
					version = "0.7.1"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "colorchoice"
 | 
				
			||||||
 | 
					version = "1.0.1"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "cpufeatures"
 | 
					name = "cpufeatures"
 | 
				
			||||||
version = "0.2.12"
 | 
					version = "0.2.12"
 | 
				
			||||||
| 
						 | 
					@ -120,6 +215,16 @@ dependencies = [
 | 
				
			||||||
 "windows-sys",
 | 
					 "windows-sys",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "eyre"
 | 
				
			||||||
 | 
					version = "0.6.12"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "indenter",
 | 
				
			||||||
 | 
					 "once_cell",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "fastrand"
 | 
					name = "fastrand"
 | 
				
			||||||
version = "2.0.1"
 | 
					version = "2.0.1"
 | 
				
			||||||
| 
						 | 
					@ -131,6 +236,8 @@ name = "fayalite"
 | 
				
			||||||
version = "0.1.0"
 | 
					version = "0.1.0"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "bitvec",
 | 
					 "bitvec",
 | 
				
			||||||
 | 
					 "clap",
 | 
				
			||||||
 | 
					 "eyre",
 | 
				
			||||||
 "fayalite-proc-macros",
 | 
					 "fayalite-proc-macros",
 | 
				
			||||||
 "fayalite-visit-gen",
 | 
					 "fayalite-visit-gen",
 | 
				
			||||||
 "hashbrown",
 | 
					 "hashbrown",
 | 
				
			||||||
| 
						 | 
					@ -208,6 +315,18 @@ dependencies = [
 | 
				
			||||||
 "allocator-api2",
 | 
					 "allocator-api2",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "heck"
 | 
				
			||||||
 | 
					version = "0.5.0"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "indenter"
 | 
				
			||||||
 | 
					version = "0.3.3"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "indexmap"
 | 
					name = "indexmap"
 | 
				
			||||||
version = "2.2.6"
 | 
					version = "2.2.6"
 | 
				
			||||||
| 
						 | 
					@ -219,6 +338,12 @@ dependencies = [
 | 
				
			||||||
 "serde",
 | 
					 "serde",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "is_terminal_polyfill"
 | 
				
			||||||
 | 
					version = "1.70.0"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "itoa"
 | 
					name = "itoa"
 | 
				
			||||||
version = "1.0.10"
 | 
					version = "1.0.10"
 | 
				
			||||||
| 
						 | 
					@ -368,6 +493,12 @@ dependencies = [
 | 
				
			||||||
 "digest",
 | 
					 "digest",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "strsim"
 | 
				
			||||||
 | 
					version = "0.11.1"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "syn"
 | 
					name = "syn"
 | 
				
			||||||
version = "2.0.66"
 | 
					version = "2.0.66"
 | 
				
			||||||
| 
						 | 
					@ -453,6 +584,12 @@ version = "1.0.12"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
 | 
					checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "utf8parse"
 | 
				
			||||||
 | 
					version = "0.2.2"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "version_check"
 | 
					name = "version_check"
 | 
				
			||||||
version = "0.9.4"
 | 
					version = "0.9.4"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -437,6 +437,7 @@ impl Visitor {
 | 
				
			||||||
                #(#lets)*
 | 
					                #(#lets)*
 | 
				
			||||||
                #make_expr_fn::<#ty>(|#infallible_var| {
 | 
					                #make_expr_fn::<#ty>(|#infallible_var| {
 | 
				
			||||||
                    let #retval_var = #check_literal;
 | 
					                    let #retval_var = #check_literal;
 | 
				
			||||||
 | 
					                    #[allow(unreachable_code)]
 | 
				
			||||||
                    match #retval_var {
 | 
					                    match #retval_var {
 | 
				
			||||||
                        #variant_or_type { .. } => #retval_var,
 | 
					                        #variant_or_type { .. } => #retval_var,
 | 
				
			||||||
                        #[allow(unreachable_patterns)]
 | 
					                        #[allow(unreachable_patterns)]
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -21,6 +21,8 @@ num-traits = { workspace = true }
 | 
				
			||||||
fayalite-proc-macros = { workspace = true }
 | 
					fayalite-proc-macros = { workspace = true }
 | 
				
			||||||
serde = { workspace = true }
 | 
					serde = { workspace = true }
 | 
				
			||||||
serde_json = { workspace = true }
 | 
					serde_json = { workspace = true }
 | 
				
			||||||
 | 
					clap = { version = "4.5.9", features = ["derive"] }
 | 
				
			||||||
 | 
					eyre = "0.6.12"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[dev-dependencies]
 | 
					[dev-dependencies]
 | 
				
			||||||
trybuild = { workspace = true }
 | 
					trybuild = { workspace = true }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										50
									
								
								crates/fayalite/examples/blinky.rs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								crates/fayalite/examples/blinky.rs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,50 @@
 | 
				
			||||||
 | 
					use clap::Parser;
 | 
				
			||||||
 | 
					use fayalite::{
 | 
				
			||||||
 | 
					    clock::{Clock, ClockDomain},
 | 
				
			||||||
 | 
					    hdl_module,
 | 
				
			||||||
 | 
					    int::{DynUInt, DynUIntType, IntTypeTrait, UInt},
 | 
				
			||||||
 | 
					    reset::{SyncReset, ToReset},
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[hdl_module]
 | 
				
			||||||
 | 
					fn blinky(clock_frequency: u64) {
 | 
				
			||||||
 | 
					    #[hdl]
 | 
				
			||||||
 | 
					    let clk: Clock = m.input();
 | 
				
			||||||
 | 
					    #[hdl]
 | 
				
			||||||
 | 
					    let rst: SyncReset = m.input();
 | 
				
			||||||
 | 
					    let cd = #[hdl]
 | 
				
			||||||
 | 
					    ClockDomain {
 | 
				
			||||||
 | 
					        clk,
 | 
				
			||||||
 | 
					        rst: rst.to_reset(),
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    let max_value = clock_frequency / 2 - 1;
 | 
				
			||||||
 | 
					    let int_ty = DynUIntType::range_inclusive(0..=max_value);
 | 
				
			||||||
 | 
					    #[hdl]
 | 
				
			||||||
 | 
					    let counter: DynUInt = m.reg_builder().clock_domain(cd).reset(int_ty.literal(0));
 | 
				
			||||||
 | 
					    #[hdl]
 | 
				
			||||||
 | 
					    let output_reg: UInt<1> = m.reg_builder().clock_domain(cd).reset_default();
 | 
				
			||||||
 | 
					    #[hdl]
 | 
				
			||||||
 | 
					    if counter == int_ty.literal(max_value) {
 | 
				
			||||||
 | 
					        m.connect(counter, int_ty.literal(0));
 | 
				
			||||||
 | 
					        m.connect(output_reg, !output_reg);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        m.connect_any(counter, counter + 1_hdl_u1);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    #[hdl]
 | 
				
			||||||
 | 
					    let led: UInt<1> = m.output();
 | 
				
			||||||
 | 
					    m.connect(led, output_reg);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Parser)]
 | 
				
			||||||
 | 
					struct Cli {
 | 
				
			||||||
 | 
					    /// clock frequency in hertz
 | 
				
			||||||
 | 
					    #[arg(long, default_value = "1000000", value_parser = clap::value_parser!(u64).range(2..))]
 | 
				
			||||||
 | 
					    clock_frequency: u64,
 | 
				
			||||||
 | 
					    #[command(subcommand)]
 | 
				
			||||||
 | 
					    cli: fayalite::cli::Cli,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn main() {
 | 
				
			||||||
 | 
					    let cli = Cli::parse();
 | 
				
			||||||
 | 
					    cli.cli.run(blinky(cli.clock_frequency))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										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())
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -18,7 +18,10 @@ use std::{
 | 
				
			||||||
    fmt,
 | 
					    fmt,
 | 
				
			||||||
    hash::Hash,
 | 
					    hash::Hash,
 | 
				
			||||||
    marker::PhantomData,
 | 
					    marker::PhantomData,
 | 
				
			||||||
    ops::{Add, BitAnd, BitOr, BitXor, Bound, Mul, Neg, Not, Range, RangeBounds, Shl, Shr, Sub},
 | 
					    ops::{
 | 
				
			||||||
 | 
					        Add, BitAnd, BitOr, BitXor, Bound, Mul, Neg, Not, Range, RangeBounds, RangeInclusive, Shl,
 | 
				
			||||||
 | 
					        Shr, Sub,
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Clone, Eq, PartialEq, Hash, Default)]
 | 
					#[derive(Clone, Eq, PartialEq, Hash, Default)]
 | 
				
			||||||
| 
						 | 
					@ -887,6 +890,15 @@ pub trait IntTypeTrait:
 | 
				
			||||||
        CanonicalType = DynSIntType,
 | 
					        CanonicalType = DynSIntType,
 | 
				
			||||||
        CanonicalValue = DynSInt,
 | 
					        CanonicalValue = DynSInt,
 | 
				
			||||||
    >;
 | 
					    >;
 | 
				
			||||||
 | 
					    fn literal(self, value: impl Into<BigInt>) -> Expr<IntValue<Self>>
 | 
				
			||||||
 | 
					    where
 | 
				
			||||||
 | 
					        Self: IntTypeTrait<
 | 
				
			||||||
 | 
					            CanonicalType = DynIntType<<Self as IntTypeTrait>::Signed>,
 | 
				
			||||||
 | 
					            CanonicalValue = DynInt<<Self as IntTypeTrait>::Signed>,
 | 
				
			||||||
 | 
					        >,
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        IntValue::with_type(self, value).to_expr()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    fn from_width_unchecked(width: usize) -> Self;
 | 
					    fn from_width_unchecked(width: usize) -> Self;
 | 
				
			||||||
    fn width(self) -> usize;
 | 
					    fn width(self) -> usize;
 | 
				
			||||||
    fn as_same_width_uint(self) -> Self::SameWidthUInt;
 | 
					    fn as_same_width_uint(self) -> Self::SameWidthUInt;
 | 
				
			||||||
| 
						 | 
					@ -994,6 +1006,66 @@ impl DynUIntType {
 | 
				
			||||||
    pub fn mask(self) -> BigUint {
 | 
					    pub fn mask(self) -> BigUint {
 | 
				
			||||||
        self.modulo() - 1u8
 | 
					        self.modulo() - 1u8
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    /// gets the smallest `UInt` that fits `v` losslessly
 | 
				
			||||||
 | 
					    pub fn for_value(v: impl Into<BigUint>) -> Self {
 | 
				
			||||||
 | 
					        let v: BigUint = v.into();
 | 
				
			||||||
 | 
					        Self::new(v.bits().try_into().expect("too big"))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    /// gets the smallest `UInt` that fits `r` losslessly, panics if `r` is empty
 | 
				
			||||||
 | 
					    #[track_caller]
 | 
				
			||||||
 | 
					    pub fn range(r: Range<impl Into<BigUint>>) -> Self {
 | 
				
			||||||
 | 
					        let start: BigUint = r.start.into();
 | 
				
			||||||
 | 
					        let end: BigUint = r.end.into();
 | 
				
			||||||
 | 
					        assert!(!end.is_zero(), "empty range");
 | 
				
			||||||
 | 
					        Self::range_inclusive(start..=(end - 1u8))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    /// gets the smallest `UInt` that fits `r` losslessly, panics if `r` is empty
 | 
				
			||||||
 | 
					    #[track_caller]
 | 
				
			||||||
 | 
					    pub fn range_inclusive(r: RangeInclusive<impl Into<BigUint>>) -> Self {
 | 
				
			||||||
 | 
					        let (start, end) = r.into_inner();
 | 
				
			||||||
 | 
					        let start: BigUint = start.into();
 | 
				
			||||||
 | 
					        let end: BigUint = end.into();
 | 
				
			||||||
 | 
					        assert!(start <= end, "empty range");
 | 
				
			||||||
 | 
					        // no need to check `start`` since it's no larger than `end`
 | 
				
			||||||
 | 
					        // so must not take more bits than `end`
 | 
				
			||||||
 | 
					        Self::for_value(end)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl DynSIntType {
 | 
				
			||||||
 | 
					    /// gets the smallest `SInt` that fits `v` losslessly
 | 
				
			||||||
 | 
					    pub fn for_value(v: impl Into<BigInt>) -> Self {
 | 
				
			||||||
 | 
					        let v: BigInt = v.into();
 | 
				
			||||||
 | 
					        Self::new(
 | 
				
			||||||
 | 
					            match v.sign() {
 | 
				
			||||||
 | 
					                Sign::Minus => {
 | 
				
			||||||
 | 
					                    // account for sign bit and for the minimum value of an `SInt`
 | 
				
			||||||
 | 
					                    // being the negative of the maximum value minus one.
 | 
				
			||||||
 | 
					                    v.not().bits().checked_add(1).expect("too big")
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                Sign::NoSign => 0,
 | 
				
			||||||
 | 
					                Sign::Plus => v.bits(),
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            .try_into()
 | 
				
			||||||
 | 
					            .expect("too big"),
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    /// gets the smallest `SInt` that fits `r` losslessly, panics if `r` is empty
 | 
				
			||||||
 | 
					    #[track_caller]
 | 
				
			||||||
 | 
					    pub fn range(r: Range<impl Into<BigInt>>) -> Self {
 | 
				
			||||||
 | 
					        let start: BigInt = r.start.into();
 | 
				
			||||||
 | 
					        let end: BigInt = r.end.into();
 | 
				
			||||||
 | 
					        Self::range_inclusive(start..=(end - 1))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    /// gets the smallest `SInt` that fits `r` losslessly, panics if `r` is empty
 | 
				
			||||||
 | 
					    #[track_caller]
 | 
				
			||||||
 | 
					    pub fn range_inclusive(r: RangeInclusive<impl Into<BigInt>>) -> Self {
 | 
				
			||||||
 | 
					        let (start, end) = r.into_inner();
 | 
				
			||||||
 | 
					        let start: BigInt = start.into();
 | 
				
			||||||
 | 
					        let end: BigInt = end.into();
 | 
				
			||||||
 | 
					        assert!(start <= end, "empty range");
 | 
				
			||||||
 | 
					        Self::new(Self::for_value(start).width.max(Self::for_value(end).width))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<Signed: GenericConstBool> sealed::Sealed for DynIntType<Signed> {}
 | 
					impl<Signed: GenericConstBool> sealed::Sealed for DynIntType<Signed> {}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -27,6 +27,7 @@ pub mod _docs;
 | 
				
			||||||
pub mod annotations;
 | 
					pub mod annotations;
 | 
				
			||||||
pub mod array;
 | 
					pub mod array;
 | 
				
			||||||
pub mod bundle;
 | 
					pub mod bundle;
 | 
				
			||||||
 | 
					pub mod cli;
 | 
				
			||||||
pub mod clock;
 | 
					pub mod clock;
 | 
				
			||||||
pub mod enum_;
 | 
					pub mod enum_;
 | 
				
			||||||
pub mod expr;
 | 
					pub mod expr;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue