use celox::{BigUint, Simulator};
#[path = "test_utils/mod.rs"]
#[macro_use]
mod test_utils;
all_backends! {
fn test_shift_in_if_reset(sim) {
@ignore_on(veryl);
@setup { let code = r#"
module Top (
clk: input clock,
rst: input reset_async_high,
a: input logic<8>,
o: output logic<8>
) {
var r: logic<8>;
always_ff (clk, rst) {
if_reset {
r = 0;
} else {
r = a << 2;
}
}
assign o = r;
}
"#; }
@build Simulator::builder(code, "Top");
let clk = sim.event("clk");
let rst = sim.signal("rst");
let a = sim.signal("a");
let o = sim.signal("o");
sim.modify(|io| {
io.set(rst, 1u8);
io.set(a, 0x0Fu8);
})
.unwrap();
sim.tick(clk).unwrap();
assert_eq!(sim.get(o), BigUint::from(0u64), "should be 0 after reset");
sim.modify(|io| io.set(rst, 0u8)).unwrap();
sim.tick(clk).unwrap();
assert_eq!(
sim.get(o),
BigUint::from(0x3Cu64),
"shift in if_reset: got {:x}",
sim.get(o)
);
}
fn test_shift_in_for_loop(sim) {
@ignore_on(sv);
@setup { let code = r#"
module Top (
clk: input clock,
a: input logic<32>,
o: output logic<32>
) {
always_ff (clk) {
for _i in 0..1 {
o = a << 4;
}
}
}
"#; }
@build Simulator::builder(code, "Top");
let clk = sim.event("clk");
let a = sim.signal("a");
let o = sim.signal("o");
sim.modify(|io| io.set(a, 0x12345678u32)).unwrap();
sim.tick(clk).unwrap();
assert_eq!(
sim.get(o),
BigUint::from(0x23456780u32),
"shift in for: got {:x}",
sim.get(o)
);
}
fn test_shift_ifreset_for(sim) {
@ignore_on(veryl, sv);
@setup { let code = r#"
module Top (
clk: input clock,
rst: input reset_async_high,
a: input logic<8>,
o: output logic<8>
) {
var r: logic<8>;
always_ff (clk, rst) {
if_reset {
r = 8'h00;
} else {
for _i in 0..1 {
r = a << 1;
}
}
}
assign o = r;
}
"#; }
@build Simulator::builder(code, "Top");
let clk = sim.event("clk");
let rst = sim.signal("rst");
let a = sim.signal("a");
let o = sim.signal("o");
sim.modify(|io| {
io.set(rst, 1u8);
io.set(a, 0x55u8);
})
.unwrap();
sim.tick(clk).unwrap();
assert_eq!(sim.get(o), BigUint::from(0u64), "after reset");
sim.modify(|io| io.set(rst, 0u8)).unwrap();
sim.tick(clk).unwrap();
assert_eq!(
sim.get(o),
BigUint::from(0xAAu64),
"if_reset+for+shift: got {:x}",
sim.get(o)
);
}
fn test_right_shift_in_if_reset(sim) {
@setup { let code = r#"
module Top (
clk: input clock,
rst: input reset_async_high,
a: input logic<16>,
o_shr: output logic<16>,
o_shl: output logic<16>
) {
var r_shr: logic<16>;
var r_shl: logic<16>;
always_ff (clk, rst) {
if_reset {
r_shr = 0;
r_shl = 0;
} else {
r_shr = a >> 4;
r_shl = a << 4;
}
}
assign o_shr = r_shr;
assign o_shl = r_shl;
}
"#; }
@build Simulator::builder(code, "Top");
let clk = sim.event("clk");
let rst = sim.signal("rst");
let a = sim.signal("a");
let o_shr = sim.signal("o_shr");
let o_shl = sim.signal("o_shl");
sim.modify(|io| {
io.set(rst, 1u8);
io.set(a, 0xABCDu16);
})
.unwrap();
sim.tick(clk).unwrap();
sim.modify(|io| io.set(rst, 0u8)).unwrap();
sim.tick(clk).unwrap();
assert_eq!(
sim.get(o_shr),
BigUint::from(0x0ABCu64),
"right shift in if_reset: got {:x}",
sim.get(o_shr)
);
assert_eq!(
sim.get(o_shl),
BigUint::from(0xBCD0u64),
"left shift in if_reset: got {:x}",
sim.get(o_shl)
);
}
fn test_dynamic_shift_in_if_reset(sim) {
@ignore_on(veryl);
@setup { let code = r#"
module Top (
clk: input clock,
rst: input reset_async_high,
a: input logic<16>,
sh: input logic<4>,
o: output logic<16>
) {
var r: logic<16>;
always_ff (clk, rst) {
if_reset {
r = 0;
} else {
r = a << sh;
}
}
assign o = r;
}
"#; }
@build Simulator::builder(code, "Top");
let clk = sim.event("clk");
let rst = sim.signal("rst");
let a = sim.signal("a");
let sh = sim.signal("sh");
let o = sim.signal("o");
sim.modify(|io| {
io.set(rst, 1u8);
io.set(a, 0x00FFu16);
io.set(sh, 4u8);
})
.unwrap();
sim.tick(clk).unwrap();
assert_eq!(sim.get(o), BigUint::from(0u64), "after reset");
sim.modify(|io| io.set(rst, 0u8)).unwrap();
sim.tick(clk).unwrap();
assert_eq!(
sim.get(o),
BigUint::from(0x0FF0u64),
"dynamic shift in if_reset: got {:x}",
sim.get(o)
);
}
fn test_shift_to_array_by_loop_index(sim) {
@ignore_on(sv);
@setup { let code = r#"
module Top (
clk: input clock,
a: input logic<8>,
o0: output logic<8>,
o1: output logic<8>,
o2: output logic<8>,
o3: output logic<8>
) {
var arr: logic<8> [4];
always_ff (clk) {
for i in 0..4 {
arr[i] = a << i;
}
}
assign o0 = arr[0];
assign o1 = arr[1];
assign o2 = arr[2];
assign o3 = arr[3];
}
"#; }
@build Simulator::builder(code, "Top");
let clk = sim.event("clk");
let a = sim.signal("a");
let o0 = sim.signal("o0");
let o1 = sim.signal("o1");
let o2 = sim.signal("o2");
let o3 = sim.signal("o3");
sim.modify(|io| io.set(a, 0x01u8)).unwrap();
sim.tick(clk).unwrap();
assert_eq!(sim.get(o0), BigUint::from(0x01u64), "arr[0] = a << 0");
assert_eq!(sim.get(o1), BigUint::from(0x02u64), "arr[1] = a << 1");
assert_eq!(sim.get(o2), BigUint::from(0x04u64), "arr[2] = a << 2");
assert_eq!(sim.get(o3), BigUint::from(0x08u64), "arr[3] = a << 3");
}
fn test_shift_with_wide_const_amount(sim) {
@ignore_on(sv);
@setup { let code = r#"
module Top (
clk: input clock,
a: input logic<8>,
o: output logic<8>
) {
always_ff (clk) {
for _i in 0..1 {
o = a << 2;
}
}
}
"#; }
@build Simulator::builder(code, "Top");
let clk = sim.event("clk");
let a = sim.signal("a");
let o = sim.signal("o");
sim.modify(|io| io.set(a, 0x0Fu8)).unwrap();
sim.tick(clk).unwrap();
assert_eq!(
sim.get(o),
BigUint::from(0x3Cu64),
"8-bit shift with 32-bit const amount: got {:x}",
sim.get(o)
);
}
}