Compare commits
No commits in common. "716c65edcd421fa3a28d271ec647188331c2d52a" and "78edfc97b2f3aec69c869999cb57acd0687ab2eb" have entirely different histories.
716c65edcd
...
78edfc97b2
4 changed files with 4 additions and 176 deletions
|
|
@ -9,7 +9,7 @@ use crate::{
|
|||
ops::ExprCastTo,
|
||||
target::{GetTarget, Target},
|
||||
},
|
||||
int::{Bool, DynSize, IntType, SIntType, SIntValue, Size, SizeType, UInt, UIntType, UIntValue},
|
||||
int::{Bool, DynSize, IntType, SIntType, SIntValue, Size, UInt, UIntType, UIntValue},
|
||||
intern::{Intern, Interned},
|
||||
memory::{DynPortType, MemPort, PortType},
|
||||
module::{
|
||||
|
|
@ -720,18 +720,3 @@ impl<T: Type> MakeUninitExpr for T {
|
|||
ops::Uninit::new(self).to_expr()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn repeat<T: Type, L: SizeType>(
|
||||
element: impl ToExpr<Type = T>,
|
||||
len: L,
|
||||
) -> Expr<ArrayType<T, L::Size>> {
|
||||
let element = element.to_expr();
|
||||
let canonical_element = Expr::canonical(element);
|
||||
ops::ArrayLiteral::new(
|
||||
Expr::ty(element),
|
||||
std::iter::repeat(canonical_element)
|
||||
.take(L::Size::as_usize(len))
|
||||
.collect(),
|
||||
)
|
||||
.to_expr()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use crate::{
|
|||
array::{Array, ArrayType},
|
||||
bundle::{Bundle, BundleType},
|
||||
clock::Clock,
|
||||
expr::{ops::BundleLiteral, repeat, Expr, Flow, ToExpr, ToLiteralBits},
|
||||
expr::{Expr, Flow, ToExpr, ToLiteralBits},
|
||||
hdl,
|
||||
int::{Bool, DynSize, Size, UInt, UIntType},
|
||||
intern::{Intern, Interned},
|
||||
|
|
@ -1050,32 +1050,3 @@ impl<Element: Type, Len: Size> MemBuilder<Element, Len> {
|
|||
.extend(annotations.into_annotations());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn splat_mask<T: Type>(ty: T, value: Expr<Bool>) -> Expr<AsMask<T>> {
|
||||
let canonical_ty = ty.canonical();
|
||||
match canonical_ty {
|
||||
CanonicalType::UInt(_)
|
||||
| CanonicalType::SInt(_)
|
||||
| CanonicalType::Bool(_)
|
||||
| CanonicalType::AsyncReset(_)
|
||||
| CanonicalType::SyncReset(_)
|
||||
| CanonicalType::Reset(_)
|
||||
| CanonicalType::Clock(_)
|
||||
| CanonicalType::Enum(_) => Expr::from_canonical(Expr::canonical(value)),
|
||||
CanonicalType::Array(array) => Expr::from_canonical(Expr::canonical(repeat(
|
||||
splat_mask(array.element(), value),
|
||||
array.len(),
|
||||
))),
|
||||
CanonicalType::Bundle(bundle) => Expr::from_canonical(Expr::canonical(
|
||||
BundleLiteral::new(
|
||||
bundle.mask_type(),
|
||||
bundle
|
||||
.fields()
|
||||
.iter()
|
||||
.map(|field| splat_mask(field.ty, value))
|
||||
.collect(),
|
||||
)
|
||||
.to_expr(),
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ pub use crate::{
|
|||
clock::{Clock, ClockDomain, ToClock},
|
||||
enum_::{HdlNone, HdlOption, HdlSome},
|
||||
expr::{
|
||||
repeat, CastBitsTo, CastTo, CastToBits, Expr, HdlPartialEq, HdlPartialOrd, MakeUninitExpr,
|
||||
CastBitsTo, CastTo, CastToBits, Expr, HdlPartialEq, HdlPartialOrd, MakeUninitExpr,
|
||||
ReduceBits, ToExpr,
|
||||
},
|
||||
hdl, hdl_module,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
// See Notices.txt for copyright information
|
||||
use crate::{memory::splat_mask, prelude::*};
|
||||
use std::num::NonZeroUsize;
|
||||
use crate::prelude::*;
|
||||
|
||||
#[hdl]
|
||||
pub struct ReadyValid<T> {
|
||||
|
|
@ -35,130 +34,3 @@ impl<T: Type> ReadyValid<T> {
|
|||
mapped
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: needs testing
|
||||
#[hdl_module]
|
||||
pub fn queue<T: Type>(
|
||||
ty: T,
|
||||
capacity: NonZeroUsize,
|
||||
inp_ready_is_comb: bool,
|
||||
out_valid_is_comb: bool,
|
||||
) {
|
||||
let count_ty = UInt::range_inclusive(0..=capacity.get());
|
||||
let index_ty = UInt::range(0..capacity.get());
|
||||
|
||||
#[hdl]
|
||||
let cd: ClockDomain = m.input();
|
||||
#[hdl]
|
||||
let inp: ReadyValid<T> = m.input(ReadyValid[ty]);
|
||||
#[hdl]
|
||||
let out: ReadyValid<T> = m.output(ReadyValid[ty]);
|
||||
#[hdl]
|
||||
let count: UInt = m.output(count_ty);
|
||||
|
||||
#[hdl]
|
||||
let inp_index = reg_builder().clock_domain(cd).reset(0.cast_to(index_ty));
|
||||
#[hdl]
|
||||
let out_index = reg_builder().clock_domain(cd).reset(0.cast_to(index_ty));
|
||||
#[hdl]
|
||||
let maybe_full = reg_builder().clock_domain(cd).reset(false);
|
||||
|
||||
#[hdl]
|
||||
let mut mem = memory(ty);
|
||||
mem.depth(capacity.get());
|
||||
let read_port = mem.new_read_port();
|
||||
let write_port = mem.new_write_port();
|
||||
|
||||
#[hdl]
|
||||
let inp_fire: Bool = wire();
|
||||
connect(inp_fire, ReadyValid::fire(inp));
|
||||
#[hdl]
|
||||
let out_fire: Bool = wire();
|
||||
connect(out_fire, ReadyValid::fire(out));
|
||||
#[hdl]
|
||||
let indexes_equal: Bool = wire();
|
||||
connect(indexes_equal, inp_index.cmp_eq(out_index));
|
||||
#[hdl]
|
||||
let empty: Bool = wire();
|
||||
connect(empty, indexes_equal & !maybe_full);
|
||||
#[hdl]
|
||||
let full: Bool = wire();
|
||||
connect(full, indexes_equal & maybe_full);
|
||||
|
||||
connect(read_port.addr, out_index);
|
||||
connect(read_port.en, true);
|
||||
connect(read_port.clk, cd.clk);
|
||||
connect(write_port.addr, inp_index);
|
||||
connect(write_port.en, inp_fire);
|
||||
connect(write_port.clk, cd.clk);
|
||||
connect(write_port.data, HdlOption::unwrap_or(inp.data, ty.uninit()));
|
||||
connect(write_port.mask, splat_mask(ty, true.to_expr()));
|
||||
|
||||
connect(inp.ready, !full);
|
||||
if inp_ready_is_comb {
|
||||
#[hdl]
|
||||
if out.ready {
|
||||
connect(inp.ready, true);
|
||||
}
|
||||
}
|
||||
|
||||
#[hdl]
|
||||
if !empty {
|
||||
connect(out.data, HdlSome(read_port.data));
|
||||
} else {
|
||||
if out_valid_is_comb {
|
||||
connect(out.data, inp.data);
|
||||
} else {
|
||||
connect(out.data, HdlOption[ty].HdlNone());
|
||||
}
|
||||
}
|
||||
|
||||
#[hdl]
|
||||
if inp_fire.cmp_ne(out_fire) {
|
||||
connect(maybe_full, inp_fire);
|
||||
}
|
||||
|
||||
#[hdl]
|
||||
if inp_fire {
|
||||
#[hdl]
|
||||
if inp_index.cmp_eq(capacity) {
|
||||
connect_any(inp_index, 0_hdl_u0);
|
||||
} else {
|
||||
connect_any(inp_index, inp_index + 1_hdl_u1);
|
||||
}
|
||||
}
|
||||
|
||||
#[hdl]
|
||||
if out_fire {
|
||||
#[hdl]
|
||||
if out_index.cmp_eq(capacity) {
|
||||
connect_any(out_index, 0_hdl_u0);
|
||||
} else {
|
||||
connect_any(out_index, out_index + 1_hdl_u1);
|
||||
}
|
||||
}
|
||||
|
||||
#[hdl]
|
||||
if indexes_equal {
|
||||
connect(
|
||||
count,
|
||||
maybe_full.cast_to_static::<UInt<1>>() << (count_ty.width() - 1),
|
||||
);
|
||||
} else {
|
||||
if capacity.is_power_of_two() {
|
||||
debug_assert_eq!(count_ty.width(), index_ty.width() + 1);
|
||||
#[hdl]
|
||||
let count_lower = wire(index_ty);
|
||||
connect(count_lower, (inp_index - out_index).cast_to(index_ty)); // wrap
|
||||
connect(count, count_lower.cast_to(count_ty));
|
||||
} else {
|
||||
debug_assert_eq!(count_ty.width(), index_ty.width());
|
||||
#[hdl]
|
||||
if inp_index.cmp_lt(out_index) {
|
||||
connect(count, inp_index + capacity - out_index);
|
||||
} else {
|
||||
connect(count, inp_index - out_index);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue