use super::constant::*;
use super::context::*;
use super::instance::*;
use super::mem::*;
use super::module::*;
use super::register::*;
use std::hash::{Hash, Hasher};
use std::ops::{Add, BitAnd, BitOr, BitXor, Mul, Not, Shl, Shr, Sub};
use std::ptr;
pub const MIN_SIGNAL_BIT_WIDTH: u32 = 1;
pub const MAX_SIGNAL_BIT_WIDTH: u32 = 128;
#[must_use]
pub struct Signal<'a> {
pub(super) context: &'a Context<'a>,
pub(super) module: &'a Module<'a>,
pub(crate) data: SignalData<'a>,
}
impl<'a> Signal<'a> {
#[must_use]
pub fn bit_width(&self) -> u32 {
match self.data {
SignalData::Lit { bit_width, .. } => bit_width,
SignalData::Input { bit_width, .. } => bit_width,
SignalData::Reg { ref data } => data.bit_width,
SignalData::UnOp { bit_width, .. } => bit_width,
SignalData::SimpleBinOp { bit_width, .. } => bit_width,
SignalData::AdditiveBinOp { bit_width, .. } => bit_width,
SignalData::ComparisonBinOp { .. } => 1,
SignalData::ShiftBinOp { bit_width, .. } => bit_width,
SignalData::Mul { bit_width, .. } => bit_width,
SignalData::MulSigned { bit_width, .. } => bit_width,
SignalData::Bits {
range_high,
range_low,
..
} => range_high - range_low + 1,
SignalData::Repeat { bit_width, .. } => bit_width,
SignalData::Concat { bit_width, .. } => bit_width,
SignalData::Mux { bit_width, .. } => bit_width,
SignalData::InstanceOutput { bit_width, .. } => bit_width,
SignalData::MemReadPortOutput { mem, .. } => mem.element_bit_width,
}
}
pub fn bit(&'a self, index: u32) -> &Signal<'a> {
if index >= self.bit_width() {
panic!("Attempted to take bit index {} from a signal with a width of {} bits. Bit indices must be in the range [0, {}] for a signal with a width of {} bits.", index, self.bit_width(), self.bit_width() - 1, self.bit_width());
}
self.context.signal_arena.alloc(Signal {
context: self.context,
module: self.module,
data: SignalData::Bits {
source: self,
range_high: index,
range_low: index,
},
})
}
pub fn bits(&'a self, range_high: u32, range_low: u32) -> &Signal<'a> {
if range_low >= self.bit_width() {
panic!("Cannot specify a range of bits where the lower bound is greater than or equal to the number of bits in the source signal. The bounds must be in the range [0, {}] for a signal with a width of {} bits, but a lower bound of {} was given.", self.bit_width() - 1, self.bit_width(), range_low);
}
if range_high >= self.bit_width() {
panic!("Cannot specify a range of bits where the upper bound is greater than or equal to the number of bits in the source signal. The bounds must be in the range [0, {}] for a signal with a width of {} bits, but an upper bound of {} was given.", self.bit_width() - 1, self.bit_width(), range_high);
}
if range_low > range_high {
panic!("Cannot specify a range of bits where the lower bound is greater than the upper bound.");
}
self.context.signal_arena.alloc(Signal {
context: self.context,
module: self.module,
data: SignalData::Bits {
source: self,
range_high,
range_low,
},
})
}
pub fn repeat(&'a self, count: u32) -> &Signal<'a> {
let bit_width = self.bit_width() * count;
if bit_width < MIN_SIGNAL_BIT_WIDTH {
panic!("Attempted to repeat a {}-bit signal {} times, but this would result in a bit width of {}, which is less than the minimal signal bit width of {} bit(s).", self.bit_width(), count, bit_width, MIN_SIGNAL_BIT_WIDTH);
}
if bit_width > MAX_SIGNAL_BIT_WIDTH {
panic!("Attempted to repeat a {}-bit signal {} times, but this would result in a bit width of {}, which is greater than the maximum signal bit width of {} bit(s).", self.bit_width(), count, bit_width, MAX_SIGNAL_BIT_WIDTH);
}
self.context.signal_arena.alloc(Signal {
context: self.context,
module: self.module,
data: SignalData::Repeat {
source: self,
count,
bit_width,
},
})
}
pub fn concat(&'a self, rhs: &'a Signal<'a>) -> &Signal<'a> {
if !ptr::eq(self.module, rhs.module) {
panic!("Attempted to combine signals from different modules.");
}
let bit_width = self.bit_width() + rhs.bit_width();
if bit_width > MAX_SIGNAL_BIT_WIDTH {
panic!("Attempted to concatenate signals with {} bit(s) and {} bit(s) respectively, but this would result in a bit width of {}, which is greater than the maximum signal bit width of {} bit(s).", self.bit_width(), rhs.bit_width(), bit_width, MAX_SIGNAL_BIT_WIDTH);
}
self.context.signal_arena.alloc(Signal {
context: self.context,
module: self.module,
data: SignalData::Concat {
lhs: self,
rhs,
bit_width,
},
})
}
pub fn eq(&'a self, rhs: &'a Signal<'a>) -> &Signal<'a> {
if !ptr::eq(self.module, rhs.module) {
panic!("Attempted to combine signals from different modules.");
}
if self.bit_width() != rhs.bit_width() {
panic!(
"Signals have different bit widths ({} and {}, respectively).",
self.bit_width(),
rhs.bit_width()
);
}
self.context.signal_arena.alloc(Signal {
context: self.context,
module: self.module,
data: SignalData::ComparisonBinOp {
lhs: self,
rhs,
op: ComparisonBinOp::Equal,
},
})
}
pub fn ne(&'a self, rhs: &'a Signal<'a>) -> &Signal<'a> {
if !ptr::eq(self.module, rhs.module) {
panic!("Attempted to combine signals from different modules.");
}
if self.bit_width() != rhs.bit_width() {
panic!(
"Signals have different bit widths ({} and {}, respectively).",
self.bit_width(),
rhs.bit_width()
);
}
self.context.signal_arena.alloc(Signal {
context: self.context,
module: self.module,
data: SignalData::ComparisonBinOp {
lhs: self,
rhs,
op: ComparisonBinOp::NotEqual,
},
})
}
pub fn lt(&'a self, rhs: &'a Signal<'a>) -> &Signal<'a> {
if !ptr::eq(self.module, rhs.module) {
panic!("Attempted to combine signals from different modules.");
}
if self.bit_width() != rhs.bit_width() {
panic!(
"Signals have different bit widths ({} and {}, respectively).",
self.bit_width(),
rhs.bit_width()
);
}
self.context.signal_arena.alloc(Signal {
context: self.context,
module: self.module,
data: SignalData::ComparisonBinOp {
lhs: self,
rhs,
op: ComparisonBinOp::LessThan,
},
})
}
pub fn le(&'a self, rhs: &'a Signal<'a>) -> &Signal<'a> {
if !ptr::eq(self.module, rhs.module) {
panic!("Attempted to combine signals from different modules.");
}
if self.bit_width() != rhs.bit_width() {
panic!(
"Signals have different bit widths ({} and {}, respectively).",
self.bit_width(),
rhs.bit_width()
);
}
self.context.signal_arena.alloc(Signal {
context: self.context,
module: self.module,
data: SignalData::ComparisonBinOp {
lhs: self,
rhs,
op: ComparisonBinOp::LessThanEqual,
},
})
}
pub fn gt(&'a self, rhs: &'a Signal<'a>) -> &Signal<'a> {
if !ptr::eq(self.module, rhs.module) {
panic!("Attempted to combine signals from different modules.");
}
if self.bit_width() != rhs.bit_width() {
panic!(
"Signals have different bit widths ({} and {}, respectively).",
self.bit_width(),
rhs.bit_width()
);
}
self.context.signal_arena.alloc(Signal {
context: self.context,
module: self.module,
data: SignalData::ComparisonBinOp {
lhs: self,
rhs,
op: ComparisonBinOp::GreaterThan,
},
})
}
pub fn ge(&'a self, rhs: &'a Signal<'a>) -> &Signal<'a> {
if !ptr::eq(self.module, rhs.module) {
panic!("Attempted to combine signals from different modules.");
}
if self.bit_width() != rhs.bit_width() {
panic!(
"Signals have different bit widths ({} and {}, respectively).",
self.bit_width(),
rhs.bit_width()
);
}
self.context.signal_arena.alloc(Signal {
context: self.context,
module: self.module,
data: SignalData::ComparisonBinOp {
lhs: self,
rhs,
op: ComparisonBinOp::GreaterThanEqual,
},
})
}
pub fn lt_signed(&'a self, rhs: &'a Signal<'a>) -> &Signal<'a> {
if !ptr::eq(self.module, rhs.module) {
panic!("Attempted to combine signals from different modules.");
}
if self.bit_width() != rhs.bit_width() {
panic!(
"Signals have different bit widths ({} and {}, respectively).",
self.bit_width(),
rhs.bit_width()
);
}
if self.bit_width() == 1 {
panic!("Cannot perform signed comparison of 1-bit signals.");
}
self.context.signal_arena.alloc(Signal {
context: self.context,
module: self.module,
data: SignalData::ComparisonBinOp {
lhs: self,
rhs,
op: ComparisonBinOp::LessThanSigned,
},
})
}
pub fn le_signed(&'a self, rhs: &'a Signal<'a>) -> &Signal<'a> {
if !ptr::eq(self.module, rhs.module) {
panic!("Attempted to combine signals from different modules.");
}
if self.bit_width() != rhs.bit_width() {
panic!(
"Signals have different bit widths ({} and {}, respectively).",
self.bit_width(),
rhs.bit_width()
);
}
if self.bit_width() == 1 {
panic!("Cannot perform signed comparison of 1-bit signals.");
}
self.context.signal_arena.alloc(Signal {
context: self.context,
module: self.module,
data: SignalData::ComparisonBinOp {
lhs: self,
rhs,
op: ComparisonBinOp::LessThanEqualSigned,
},
})
}
pub fn gt_signed(&'a self, rhs: &'a Signal<'a>) -> &Signal<'a> {
if !ptr::eq(self.module, rhs.module) {
panic!("Attempted to combine signals from different modules.");
}
if self.bit_width() != rhs.bit_width() {
panic!(
"Signals have different bit widths ({} and {}, respectively).",
self.bit_width(),
rhs.bit_width()
);
}
if self.bit_width() == 1 {
panic!("Cannot perform signed comparison of 1-bit signals.");
}
self.context.signal_arena.alloc(Signal {
context: self.context,
module: self.module,
data: SignalData::ComparisonBinOp {
lhs: self,
rhs,
op: ComparisonBinOp::GreaterThanSigned,
},
})
}
pub fn ge_signed(&'a self, rhs: &'a Signal<'a>) -> &Signal<'a> {
if !ptr::eq(self.module, rhs.module) {
panic!("Attempted to combine signals from different modules.");
}
if self.bit_width() != rhs.bit_width() {
panic!(
"Signals have different bit widths ({} and {}, respectively).",
self.bit_width(),
rhs.bit_width()
);
}
if self.bit_width() == 1 {
panic!("Cannot perform signed comparison of 1-bit signals.");
}
self.context.signal_arena.alloc(Signal {
context: self.context,
module: self.module,
data: SignalData::ComparisonBinOp {
lhs: self,
rhs,
op: ComparisonBinOp::GreaterThanEqualSigned,
},
})
}
pub fn shr_arithmetic(&'a self, rhs: &'a Signal<'a>) -> &Signal<'a> {
if !ptr::eq(self.module, rhs.module) {
panic!("Attempted to combine signals from different modules.");
}
self.context.signal_arena.alloc(Signal {
context: self.context,
module: self.module,
data: SignalData::ShiftBinOp {
lhs: self,
rhs,
op: ShiftBinOp::ShrArithmetic,
bit_width: self.bit_width(),
},
})
}
pub fn mul_signed(&'a self, rhs: &'a Signal<'a>) -> &Signal<'a> {
if !ptr::eq(self.module, rhs.module) {
panic!("Attempted to combine signals from different modules.");
}
let bit_width = self.bit_width() + rhs.bit_width();
if bit_width > MAX_SIGNAL_BIT_WIDTH {
panic!("Attempted to multiply a {}-bit with a {}-bit signal, but this would result in a bit width of {}, which is greater than the maximum signal bit width of {} bit(s).", self.bit_width(), rhs.bit_width(), bit_width, MAX_SIGNAL_BIT_WIDTH);
}
self.context.signal_arena.alloc(Signal {
context: self.context,
module: self.module,
data: SignalData::MulSigned {
lhs: self,
rhs,
bit_width,
},
})
}
pub fn mux(&'a self, when_true: &'a Signal<'a>, when_false: &'a Signal<'a>) -> &Signal<'a> {
self.module.mux(self, when_true, when_false)
}
pub fn reg_next<S: Into<String>>(&'a self, name: S) -> &Signal<'a> {
let reg = self.module.reg(name, self.bit_width());
reg.drive_next(self);
reg.value
}
pub fn reg_next_with_default<S: Into<String>, C: Into<Constant>>(
&'a self,
name: S,
default_value: C,
) -> &Signal<'a> {
let reg = self.module.reg(name, self.bit_width());
reg.default_value(default_value);
reg.drive_next(self);
reg.value
}
}
pub(crate) enum SignalData<'a> {
Lit {
value: Constant,
bit_width: u32,
},
Input {
name: String,
bit_width: u32,
},
Reg {
data: &'a RegisterData<'a>,
},
UnOp {
source: &'a Signal<'a>,
op: UnOp,
bit_width: u32,
},
SimpleBinOp {
lhs: &'a Signal<'a>,
rhs: &'a Signal<'a>,
op: SimpleBinOp,
bit_width: u32,
},
AdditiveBinOp {
lhs: &'a Signal<'a>,
rhs: &'a Signal<'a>,
op: AdditiveBinOp,
bit_width: u32,
},
ComparisonBinOp {
lhs: &'a Signal<'a>,
rhs: &'a Signal<'a>,
op: ComparisonBinOp,
},
ShiftBinOp {
lhs: &'a Signal<'a>,
rhs: &'a Signal<'a>,
op: ShiftBinOp,
bit_width: u32,
},
Mul {
lhs: &'a Signal<'a>,
rhs: &'a Signal<'a>,
bit_width: u32,
},
MulSigned {
lhs: &'a Signal<'a>,
rhs: &'a Signal<'a>,
bit_width: u32,
},
Bits {
source: &'a Signal<'a>,
range_high: u32,
range_low: u32,
},
Repeat {
source: &'a Signal<'a>,
count: u32,
bit_width: u32,
},
Concat {
lhs: &'a Signal<'a>,
rhs: &'a Signal<'a>,
bit_width: u32,
},
Mux {
cond: &'a Signal<'a>,
when_true: &'a Signal<'a>,
when_false: &'a Signal<'a>,
bit_width: u32,
},
InstanceOutput {
instance: &'a Instance<'a>,
name: String,
bit_width: u32,
},
MemReadPortOutput {
mem: &'a Mem<'a>,
address: &'a Signal<'a>,
enable: &'a Signal<'a>,
},
}
impl<'a> Add for &'a Signal<'a> {
type Output = Self;
fn add(self, rhs: Self) -> Self {
if !ptr::eq(self.module, rhs.module) {
panic!("Attempted to combine signals from different modules.");
}
if self.bit_width() != rhs.bit_width() {
panic!(
"Signals have different bit widths ({} and {}, respectively).",
self.bit_width(),
rhs.bit_width()
);
}
self.context.signal_arena.alloc(Signal {
context: self.context,
module: self.module,
data: SignalData::AdditiveBinOp {
lhs: self,
rhs,
op: AdditiveBinOp::Add,
bit_width: self.bit_width(),
},
})
}
}
impl<'a> BitAnd for &'a Signal<'a> {
type Output = Self;
fn bitand(self, rhs: Self) -> Self {
if !ptr::eq(self.module, rhs.module) {
panic!("Attempted to combine signals from different modules.");
}
if self.bit_width() != rhs.bit_width() {
panic!(
"Signals have different bit widths ({} and {}, respectively).",
self.bit_width(),
rhs.bit_width()
);
}
self.context.signal_arena.alloc(Signal {
context: self.context,
module: self.module,
data: SignalData::SimpleBinOp {
lhs: self,
rhs,
op: SimpleBinOp::BitAnd,
bit_width: self.bit_width(),
},
})
}
}
impl<'a> BitOr for &'a Signal<'a> {
type Output = Self;
fn bitor(self, rhs: Self) -> Self {
if !ptr::eq(self.module, rhs.module) {
panic!("Attempted to combine signals from different modules.");
}
if self.bit_width() != rhs.bit_width() {
panic!(
"Signals have different bit widths ({} and {}, respectively).",
self.bit_width(),
rhs.bit_width()
);
}
self.context.signal_arena.alloc(Signal {
context: self.context,
module: self.module,
data: SignalData::SimpleBinOp {
lhs: self,
rhs,
op: SimpleBinOp::BitOr,
bit_width: self.bit_width(),
},
})
}
}
impl<'a> BitXor for &'a Signal<'a> {
type Output = Self;
fn bitxor(self, rhs: Self) -> Self {
if !ptr::eq(self.module, rhs.module) {
panic!("Attempted to combine signals from different modules.");
}
if self.bit_width() != rhs.bit_width() {
panic!(
"Signals have different bit widths ({} and {}, respectively).",
self.bit_width(),
rhs.bit_width()
);
}
self.context.signal_arena.alloc(Signal {
context: self.context,
module: self.module,
data: SignalData::SimpleBinOp {
lhs: self,
rhs,
op: SimpleBinOp::BitXor,
bit_width: self.bit_width(),
},
})
}
}
impl<'a> Eq for &'a Signal<'a> {}
impl<'a> Hash for &'a Signal<'a> {
fn hash<H: Hasher>(&self, state: &mut H) {
state.write_usize(*self as *const _ as usize)
}
}
impl<'a> PartialEq for &'a Signal<'a> {
fn eq(&self, other: &Self) -> bool {
ptr::eq(*self, *other)
}
}
impl<'a> Mul for &'a Signal<'a> {
type Output = Self;
fn mul(self, rhs: Self) -> Self {
if !ptr::eq(self.module, rhs.module) {
panic!("Attempted to combine signals from different modules.");
}
let bit_width = self.bit_width() + rhs.bit_width();
if bit_width > MAX_SIGNAL_BIT_WIDTH {
panic!("Attempted to multiply a {}-bit with a {}-bit signal, but this would result in a bit width of {}, which is greater than the maximum signal bit width of {} bit(s).", self.bit_width(), rhs.bit_width(), bit_width, MAX_SIGNAL_BIT_WIDTH);
}
self.context.signal_arena.alloc(Signal {
context: self.context,
module: self.module,
data: SignalData::Mul {
lhs: self,
rhs,
bit_width,
},
})
}
}
impl<'a> Not for &'a Signal<'a> {
type Output = Self;
fn not(self) -> Self {
self.context.signal_arena.alloc(Signal {
context: self.context,
module: self.module,
data: SignalData::UnOp {
source: self,
op: UnOp::Not,
bit_width: self.bit_width(),
},
})
}
}
impl<'a> Shl for &'a Signal<'a> {
type Output = Self;
fn shl(self, rhs: Self) -> Self {
if !ptr::eq(self.module, rhs.module) {
panic!("Attempted to combine signals from different modules.");
}
self.context.signal_arena.alloc(Signal {
context: self.context,
module: self.module,
data: SignalData::ShiftBinOp {
lhs: self,
rhs,
op: ShiftBinOp::Shl,
bit_width: self.bit_width(),
},
})
}
}
impl<'a> Shr for &'a Signal<'a> {
type Output = Self;
fn shr(self, rhs: Self) -> Self {
if !ptr::eq(self.module, rhs.module) {
panic!("Attempted to combine signals from different modules.");
}
self.context.signal_arena.alloc(Signal {
context: self.context,
module: self.module,
data: SignalData::ShiftBinOp {
lhs: self,
rhs,
op: ShiftBinOp::Shr,
bit_width: self.bit_width(),
},
})
}
}
impl<'a> Sub for &'a Signal<'a> {
type Output = Self;
fn sub(self, rhs: Self) -> Self {
if !ptr::eq(self.module, rhs.module) {
panic!("Attempted to combine signals from different modules.");
}
if self.bit_width() != rhs.bit_width() {
panic!(
"Signals have different bit widths ({} and {}, respectively).",
self.bit_width(),
rhs.bit_width()
);
}
self.context.signal_arena.alloc(Signal {
context: self.context,
module: self.module,
data: SignalData::AdditiveBinOp {
lhs: self,
rhs,
op: AdditiveBinOp::Sub,
bit_width: self.bit_width(),
},
})
}
}
#[derive(Clone, Copy)]
pub(crate) enum UnOp {
Not,
}
#[derive(Clone, Copy)]
pub(crate) enum SimpleBinOp {
BitAnd,
BitOr,
BitXor,
}
#[derive(Clone, Copy)]
pub(crate) enum ComparisonBinOp {
Equal,
GreaterThan,
GreaterThanEqual,
GreaterThanEqualSigned,
GreaterThanSigned,
LessThan,
LessThanEqual,
LessThanEqualSigned,
LessThanSigned,
NotEqual,
}
#[derive(Clone, Copy)]
pub(crate) enum AdditiveBinOp {
Add,
Sub,
}
#[derive(Clone, Copy)]
pub(crate) enum ShiftBinOp {
Shl,
Shr,
ShrArithmetic,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
#[should_panic(
expected = "Attempted to take bit index 3 from a signal with a width of 3 bits. Bit indices must be in the range [0, 2] for a signal with a width of 3 bits."
)]
fn bit_index_oob_error() {
let c = Context::new();
let m = c.module("A");
let i = m.input("i", 3);
let _ = i.bit(0); let _ = i.bit(1); let _ = i.bit(2);
let _ = i.bit(3); }
#[test]
#[should_panic(
expected = "Cannot specify a range of bits where the lower bound is greater than or equal to the number of bits in the source signal. The bounds must be in the range [0, 2] for a signal with a width of 3 bits, but a lower bound of 3 was given."
)]
fn bits_range_low_oob_error() {
let c = Context::new();
let m = c.module("A");
let i = m.input("i", 3);
let _ = i.bits(4, 3);
}
#[test]
#[should_panic(
expected = "Cannot specify a range of bits where the upper bound is greater than or equal to the number of bits in the source signal. The bounds must be in the range [0, 2] for a signal with a width of 3 bits, but an upper bound of 3 was given."
)]
fn bits_range_high_oob_error() {
let c = Context::new();
let m = c.module("A");
let i = m.input("i", 3);
let _ = i.bits(3, 2);
}
#[test]
#[should_panic(
expected = "Cannot specify a range of bits where the lower bound is greater than the upper bound."
)]
fn bits_range_low_gt_high_error() {
let c = Context::new();
let m = c.module("A");
let i = m.input("i", 3);
let _ = i.bits(0, 1);
}
#[test]
#[should_panic(
expected = "Attempted to repeat a 1-bit signal 0 times, but this would result in a bit width of 0, which is less than the minimal signal bit width of 1 bit(s)."
)]
fn repeat_count_zero_error() {
let c = Context::new();
let m = c.module("A");
let i = m.input("i", 1);
let _ = i.repeat(0);
}
#[test]
#[should_panic(
expected = "Attempted to repeat a 1-bit signal 129 times, but this would result in a bit width of 129, which is greater than the maximum signal bit width of 128 bit(s)."
)]
fn repeat_count_oob_error() {
let c = Context::new();
let m = c.module("A");
let i = m.input("i", 1);
let _ = i.repeat(129);
}
#[test]
#[should_panic(expected = "Attempted to combine signals from different modules.")]
fn concat_separate_module_error() {
let c = Context::new();
let m1 = c.module("A");
let i1 = m1.input("a", 1);
let m2 = c.module("B");
let i2 = m2.high();
let _ = i1.concat(i2);
}
#[test]
#[should_panic(
expected = "Attempted to concatenate signals with 128 bit(s) and 1 bit(s) respectively, but this would result in a bit width of 129, which is greater than the maximum signal bit width of 128 bit(s)."
)]
fn concat_oob_error() {
let c = Context::new();
let m = c.module("A");
let i1 = m.input("i1", 128);
let i2 = m.input("i2", 1);
let _ = i1.concat(i2);
}
#[test]
#[should_panic(expected = "Attempted to combine signals from different modules.")]
fn eq_separate_module_error() {
let c = Context::new();
let m1 = c.module("A");
let i1 = m1.input("a", 1);
let m2 = c.module("B");
let i2 = m2.high();
let _ = i1.eq(i2);
}
#[test]
#[should_panic(expected = "Signals have different bit widths (3 and 5, respectively).")]
fn eq_incompatible_bit_widths_error() {
let c = Context::new();
let m = c.module("A");
let i1 = m.input("a", 3);
let i2 = m.input("b", 5);
let _ = i1.eq(i2);
}
#[test]
#[should_panic(expected = "Attempted to combine signals from different modules.")]
fn ne_separate_module_error() {
let c = Context::new();
let m1 = c.module("A");
let i1 = m1.input("a", 1);
let m2 = c.module("B");
let i2 = m2.high();
let _ = i1.ne(i2);
}
#[test]
#[should_panic(expected = "Signals have different bit widths (3 and 5, respectively).")]
fn ne_incompatible_bit_widths_error() {
let c = Context::new();
let m = c.module("A");
let i1 = m.input("a", 3);
let i2 = m.input("b", 5);
let _ = i1.ne(i2);
}
#[test]
#[should_panic(expected = "Attempted to combine signals from different modules.")]
fn lt_separate_module_error() {
let c = Context::new();
let m1 = c.module("A");
let i1 = m1.input("a", 1);
let m2 = c.module("B");
let i2 = m2.high();
let _ = i1.lt(i2);
}
#[test]
#[should_panic(expected = "Signals have different bit widths (3 and 5, respectively).")]
fn lt_incompatible_bit_widths_error() {
let c = Context::new();
let m = c.module("A");
let i1 = m.input("a", 3);
let i2 = m.input("b", 5);
let _ = i1.lt(i2);
}
#[test]
#[should_panic(expected = "Attempted to combine signals from different modules.")]
fn le_separate_module_error() {
let c = Context::new();
let m1 = c.module("A");
let i1 = m1.input("a", 1);
let m2 = c.module("B");
let i2 = m2.high();
let _ = i1.le(i2);
}
#[test]
#[should_panic(expected = "Signals have different bit widths (3 and 5, respectively).")]
fn le_incompatible_bit_widths_error() {
let c = Context::new();
let m = c.module("A");
let i1 = m.input("a", 3);
let i2 = m.input("b", 5);
let _ = i1.le(i2);
}
#[test]
#[should_panic(expected = "Attempted to combine signals from different modules.")]
fn gt_separate_module_error() {
let c = Context::new();
let m1 = c.module("A");
let i1 = m1.input("a", 1);
let m2 = c.module("B");
let i2 = m2.high();
let _ = i1.gt(i2);
}
#[test]
#[should_panic(expected = "Signals have different bit widths (3 and 5, respectively).")]
fn gt_incompatible_bit_widths_error() {
let c = Context::new();
let m = c.module("A");
let i1 = m.input("a", 3);
let i2 = m.input("b", 5);
let _ = i1.gt(i2);
}
#[test]
#[should_panic(expected = "Attempted to combine signals from different modules.")]
fn ge_separate_module_error() {
let c = Context::new();
let m1 = c.module("A");
let i1 = m1.input("a", 1);
let m2 = c.module("B");
let i2 = m2.high();
let _ = i1.ge(i2);
}
#[test]
#[should_panic(expected = "Signals have different bit widths (3 and 5, respectively).")]
fn ge_incompatible_bit_widths_error() {
let c = Context::new();
let m = c.module("A");
let i1 = m.input("a", 3);
let i2 = m.input("b", 5);
let _ = i1.ge(i2);
}
#[test]
#[should_panic(expected = "Attempted to combine signals from different modules.")]
fn lt_signed_separate_module_error() {
let c = Context::new();
let m1 = c.module("A");
let i1 = m1.input("a", 1);
let m2 = c.module("B");
let i2 = m2.high();
let _ = i1.lt_signed(i2);
}
#[test]
#[should_panic(expected = "Signals have different bit widths (3 and 5, respectively).")]
fn lt_signed_incompatible_bit_widths_error() {
let c = Context::new();
let m = c.module("A");
let i1 = m.input("a", 3);
let i2 = m.input("b", 5);
let _ = i1.lt_signed(i2);
}
#[test]
#[should_panic(expected = "Cannot perform signed comparison of 1-bit signals.")]
fn lt_signed_bit_width_1_error() {
let c = Context::new();
let m = c.module("A");
let i1 = m.input("a", 1);
let i2 = m.input("b", 1);
let _ = i1.lt_signed(i2);
}
#[test]
#[should_panic(expected = "Attempted to combine signals from different modules.")]
fn le_signed_separate_module_error() {
let c = Context::new();
let m1 = c.module("A");
let i1 = m1.input("a", 1);
let m2 = c.module("B");
let i2 = m2.high();
let _ = i1.le_signed(i2);
}
#[test]
#[should_panic(expected = "Signals have different bit widths (3 and 5, respectively).")]
fn le_signed_incompatible_bit_widths_error() {
let c = Context::new();
let m = c.module("A");
let i1 = m.input("a", 3);
let i2 = m.input("b", 5);
let _ = i1.le_signed(i2);
}
#[test]
#[should_panic(expected = "Cannot perform signed comparison of 1-bit signals.")]
fn le_signed_bit_width_1_error() {
let c = Context::new();
let m = c.module("A");
let i1 = m.input("a", 1);
let i2 = m.input("b", 1);
let _ = i1.le_signed(i2);
}
#[test]
#[should_panic(expected = "Attempted to combine signals from different modules.")]
fn gt_signed_separate_module_error() {
let c = Context::new();
let m1 = c.module("A");
let i1 = m1.input("a", 1);
let m2 = c.module("B");
let i2 = m2.high();
let _ = i1.gt_signed(i2);
}
#[test]
#[should_panic(expected = "Signals have different bit widths (3 and 5, respectively).")]
fn gt_signed_incompatible_bit_widths_error() {
let c = Context::new();
let m = c.module("A");
let i1 = m.input("a", 3);
let i2 = m.input("b", 5);
let _ = i1.gt_signed(i2);
}
#[test]
#[should_panic(expected = "Cannot perform signed comparison of 1-bit signals.")]
fn gt_signed_bit_width_1_error() {
let c = Context::new();
let m = c.module("A");
let i1 = m.input("a", 1);
let i2 = m.input("b", 1);
let _ = i1.gt_signed(i2);
}
#[test]
#[should_panic(expected = "Attempted to combine signals from different modules.")]
fn ge_signed_separate_module_error() {
let c = Context::new();
let m1 = c.module("A");
let i1 = m1.input("a", 1);
let m2 = c.module("B");
let i2 = m2.high();
let _ = i1.ge_signed(i2);
}
#[test]
#[should_panic(expected = "Signals have different bit widths (3 and 5, respectively).")]
fn ge_signed_incompatible_bit_widths_error() {
let c = Context::new();
let m = c.module("A");
let i1 = m.input("a", 3);
let i2 = m.input("b", 5);
let _ = i1.ge_signed(i2);
}
#[test]
#[should_panic(expected = "Cannot perform signed comparison of 1-bit signals.")]
fn ge_signed_bit_width_1_error() {
let c = Context::new();
let m = c.module("A");
let i1 = m.input("a", 1);
let i2 = m.input("b", 1);
let _ = i1.ge_signed(i2);
}
#[test]
#[should_panic(expected = "Attempted to combine signals from different modules.")]
fn shr_arithmetic_separate_module_error() {
let c = Context::new();
let m1 = c.module("A");
let i1 = m1.input("a", 1);
let m2 = c.module("B");
let i2 = m2.high();
let _ = i1.shr_arithmetic(i2);
}
#[test]
#[should_panic(expected = "Attempted to combine signals from different modules.")]
fn mul_signed_separate_module_error() {
let c = Context::new();
let m1 = c.module("A");
let i1 = m1.input("a", 1);
let m2 = c.module("B");
let i2 = m2.high();
let _ = i1.mul_signed(i2);
}
#[test]
#[should_panic(
expected = "Attempted to multiply a 128-bit with a 1-bit signal, but this would result in a bit width of 129, which is greater than the maximum signal bit width of 128 bit(s)."
)]
fn mul_signed_oob_error() {
let c = Context::new();
let m = c.module("A");
let i1 = m.input("a", 128);
let i2 = m.input("b", 1);
let _ = i1.mul_signed(i2);
}
#[test]
#[should_panic(expected = "Attempted to combine signals from different modules.")]
fn mux_cond_separate_module_error() {
let c = Context::new();
let a = c.module("A");
let l1 = a.lit(false, 1);
let b = c.module("B");
let l2 = b.lit(32u8, 8);
let l3 = b.lit(32u8, 8);
let _ = l1.mux(l2, l3);
}
#[test]
#[should_panic(expected = "Attempted to combine signals from different modules.")]
fn mux_when_true_separate_module_error() {
let c = Context::new();
let a = c.module("A");
let l1 = a.lit(32u8, 8);
let b = c.module("B");
let l2 = b.lit(true, 1);
let l3 = b.lit(32u8, 8);
let _ = l2.mux(l1, l3);
}
#[test]
#[should_panic(expected = "Attempted to combine signals from different modules.")]
fn mux_when_false_separate_module_error() {
let c = Context::new();
let a = c.module("A");
let l1 = a.lit(32u8, 8);
let b = c.module("B");
let l2 = b.lit(true, 1);
let l3 = b.lit(32u8, 8);
let _ = l2.mux(l3, l1);
}
#[test]
#[should_panic(expected = "Multiplexer conditionals can only be 1 bit wide.")]
fn mux_cond_bit_width_error() {
let c = Context::new();
let a = c.module("A");
let l1 = a.lit(2u8, 2);
let l2 = a.lit(32u8, 8);
let l3 = a.lit(32u8, 8);
let _ = l1.mux(l2, l3);
}
#[test]
#[should_panic(
expected = "Cannot multiplex signals with different bit widths (3 and 5, respectively)."
)]
fn mux_true_false_bit_width_error() {
let c = Context::new();
let a = c.module("A");
let l1 = a.lit(false, 1);
let l2 = a.lit(3u8, 3);
let l3 = a.lit(3u8, 5);
let _ = a.mux(l1, l2, l3);
}
#[test]
#[should_panic(expected = "Attempted to combine signals from different modules.")]
fn add_separate_module_error() {
let c = Context::new();
let m1 = c.module("A");
let i1 = m1.input("a", 1);
let m2 = c.module("B");
let i2 = m2.high();
let _ = i1 + i2;
}
#[test]
#[should_panic(expected = "Signals have different bit widths (3 and 5, respectively).")]
fn add_incompatible_bit_widths_error() {
let c = Context::new();
let m = c.module("A");
let i1 = m.input("a", 3);
let i2 = m.input("b", 5);
let _ = i1 + i2;
}
#[test]
#[should_panic(expected = "Attempted to combine signals from different modules.")]
fn bitand_separate_module_error() {
let c = Context::new();
let m1 = c.module("A");
let i1 = m1.input("a", 1);
let m2 = c.module("B");
let i2 = m2.high();
let _ = i1 & i2;
}
#[test]
#[should_panic(expected = "Signals have different bit widths (3 and 5, respectively).")]
fn bitand_incompatible_bit_widths_error() {
let c = Context::new();
let m = c.module("A");
let i1 = m.input("a", 3);
let i2 = m.input("b", 5);
let _ = i1 & i2;
}
#[test]
#[should_panic(expected = "Attempted to combine signals from different modules.")]
fn bitor_separate_module_error() {
let c = Context::new();
let m1 = c.module("A");
let i1 = m1.input("a", 1);
let m2 = c.module("B");
let i2 = m2.high();
let _ = i1 | i2;
}
#[test]
#[should_panic(expected = "Signals have different bit widths (3 and 5, respectively).")]
fn bitor_incompatible_bit_widths_error() {
let c = Context::new();
let m = c.module("A");
let i1 = m.input("a", 3);
let i2 = m.input("b", 5);
let _ = i1 | i2;
}
#[test]
#[should_panic(expected = "Attempted to combine signals from different modules.")]
fn bitxor_separate_module_error() {
let c = Context::new();
let m1 = c.module("A");
let i1 = m1.input("a", 1);
let m2 = c.module("B");
let i2 = m2.high();
let _ = i1 ^ i2;
}
#[test]
#[should_panic(expected = "Signals have different bit widths (3 and 5, respectively).")]
fn bitxor_incompatible_bit_widths_error() {
let c = Context::new();
let m = c.module("A");
let i1 = m.input("a", 3);
let i2 = m.input("b", 5);
let _ = i1 ^ i2;
}
#[test]
#[should_panic(expected = "Attempted to combine signals from different modules.")]
fn mul_separate_module_error() {
let c = Context::new();
let m1 = c.module("A");
let i1 = m1.input("a", 1);
let m2 = c.module("B");
let i2 = m2.high();
let _ = i1 * i2;
}
#[test]
#[should_panic(
expected = "Attempted to multiply a 128-bit with a 1-bit signal, but this would result in a bit width of 129, which is greater than the maximum signal bit width of 128 bit(s)."
)]
fn mul_oob_error() {
let c = Context::new();
let m = c.module("A");
let i1 = m.input("a", 128);
let i2 = m.input("b", 1);
let _ = i1 * i2;
}
#[test]
#[should_panic(expected = "Attempted to combine signals from different modules.")]
fn shl_separate_module_error() {
let c = Context::new();
let m1 = c.module("A");
let i1 = m1.input("a", 1);
let m2 = c.module("B");
let i2 = m2.high();
let _ = i1 << i2;
}
#[test]
#[should_panic(expected = "Attempted to combine signals from different modules.")]
fn shr_separate_module_error() {
let c = Context::new();
let m1 = c.module("A");
let i1 = m1.input("a", 1);
let m2 = c.module("B");
let i2 = m2.high();
let _ = i1 >> i2;
}
#[test]
#[should_panic(expected = "Attempted to combine signals from different modules.")]
fn sub_separate_module_error() {
let c = Context::new();
let m1 = c.module("A");
let i1 = m1.input("a", 1);
let m2 = c.module("B");
let i2 = m2.high();
let _ = i1 - i2;
}
#[test]
#[should_panic(expected = "Signals have different bit widths (3 and 5, respectively).")]
fn sub_incompatible_bit_widths_error() {
let c = Context::new();
let m = c.module("A");
let i1 = m.input("a", 3);
let i2 = m.input("b", 5);
let _ = i1 - i2;
}
}