Compare commits
5 commits
1809fccb45
...
a191ece9a5
Author | SHA1 | Date | |
---|---|---|---|
Jacob Lifshay | a191ece9a5 | ||
Jacob Lifshay | 23a77368b3 | ||
Jacob Lifshay | 8080cc7b5c | ||
Jacob Lifshay | bdfa18e11d | ||
Jacob Lifshay | 8ca0cd56c4 |
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…
Reference in a new issue