use bitloom_hir::{Diagnostic, Diagnostics, Span};
pub fn mask_mem_word(word: u64, width: u32) -> u64 {
if width == 0 {
0
} else if width >= 64 {
word
} else {
word & ((1u64 << width) - 1)
}
}
pub fn generate_mem_init_words<F>(depth: u32, width: u32, f: F) -> Vec<u64>
where
F: Fn(usize) -> u64,
{
(0..depth as usize)
.map(|i| mask_mem_word(f(i), width))
.collect()
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum HwCaptureKind {
Wire,
Reg,
Signal,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct HwCaptureRef {
pub kind: HwCaptureKind,
pub name: String,
}
impl HwCaptureRef {
pub fn wire(name: impl Into<String>) -> Self {
Self {
kind: HwCaptureKind::Wire,
name: name.into(),
}
}
pub fn reg(name: impl Into<String>) -> Self {
Self {
kind: HwCaptureKind::Reg,
name: name.into(),
}
}
pub fn signal(name: impl Into<String>) -> Self {
Self {
kind: HwCaptureKind::Signal,
name: name.into(),
}
}
pub(crate) fn kind_label(&self) -> &'static str {
match self.kind {
HwCaptureKind::Wire => "Wire",
HwCaptureKind::Reg => "Reg",
HwCaptureKind::Signal => "Signal",
}
}
}
pub trait SynthesizableClosure {
fn synthesizable_closure_violations(&self) -> Vec<SynthesizableClosureViolation> {
Vec::new()
}
}
#[derive(Debug, Default, Clone, Copy)]
pub struct LegalEmptyClosure;
impl SynthesizableClosure for LegalEmptyClosure {}
#[derive(Debug, Default, Clone, Copy)]
pub struct LegalSimpleClosure;
impl SynthesizableClosure for LegalSimpleClosure {}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum CombInline {
Ref(String),
Lit(u64),
Add(String, String),
Sub(String, String),
And(String, String),
Or(String, String),
Xor(String, String),
Eq(String, String),
Mux { sel: String, t: String, f: String },
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum SeqInline {
Inc,
Comb(CombInline),
}
impl From<CombInline> for SeqInline {
fn from(c: CombInline) -> Self {
Self::Comb(c)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SeqOwnershipViolationKind {
IllegalMutableBorrow,
}
impl SeqOwnershipViolationKind {
pub fn code(self) -> &'static str {
match self {
Self::IllegalMutableBorrow => "rhdl::E0146",
}
}
fn label(self) -> &'static str {
match self {
Self::IllegalMutableBorrow => "illegal mutable signal borrow",
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct SeqOwnershipViolation {
pub kind: SeqOwnershipViolationKind,
pub detail: String,
}
impl SeqOwnershipViolation {
pub fn illegal_mutable_borrow(detail: impl Into<String>) -> Self {
Self {
kind: SeqOwnershipViolationKind::IllegalMutableBorrow,
detail: detail.into(),
}
}
pub fn code(&self) -> &'static str {
self.kind.code()
}
}
pub fn diagnose_seq_ownership_violations(
violations: &[SeqOwnershipViolation],
span: Span,
) -> Diagnostics {
let mut diags = Diagnostics::default();
for v in violations {
diags.push(Diagnostic {
span,
code: v.code().into(),
en: format!(
"sequential synthesizable-closure ownership violation: {} ({}); \
Cap-R-70 forbids illegal extra mutable signal borrows / multi-drive \
patterns inside seq inline (FR75)",
v.kind.label(),
v.detail
),
zh: format!(
"时序可综合闭包所有权违规:{}({});Cap-R-70 禁止闭包体内额外非法可变信号借用/多驱动(FR75)",
v.kind.label(),
v.detail
),
});
}
diags
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SynthesizableClosureViolationKind {
Heap,
RuntimeCaptureState,
Impure,
}
impl SynthesizableClosureViolationKind {
pub fn code(self) -> &'static str {
match self {
Self::Heap => "rhdl::E0143",
Self::RuntimeCaptureState => "rhdl::E0144",
Self::Impure => "rhdl::E0145",
}
}
fn label(self) -> &'static str {
match self {
Self::Heap => "heap allocation",
Self::RuntimeCaptureState => "runtime capture state",
Self::Impure => "impure / side-effecting body",
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct SynthesizableClosureViolation {
pub kind: SynthesizableClosureViolationKind,
pub detail: String,
}
impl SynthesizableClosureViolation {
pub fn heap(detail: impl Into<String>) -> Self {
Self {
kind: SynthesizableClosureViolationKind::Heap,
detail: detail.into(),
}
}
pub fn runtime_capture_state(detail: impl Into<String>) -> Self {
Self {
kind: SynthesizableClosureViolationKind::RuntimeCaptureState,
detail: detail.into(),
}
}
pub fn impure(detail: impl Into<String>) -> Self {
Self {
kind: SynthesizableClosureViolationKind::Impure,
detail: detail.into(),
}
}
pub fn code(&self) -> &'static str {
self.kind.code()
}
}
pub fn diagnose_synthesizable_closure_violations(
violations: &[SynthesizableClosureViolation],
span: Span,
) -> Diagnostics {
let mut diags = Diagnostics::default();
for v in violations {
diags.push(Diagnostic {
span,
code: v.code().into(),
en: format!(
"synthesizable-closure violation: {} ({}); \
SynthesizableClosure requires pure, no-heap, no runtime capture state \
(FR74 / Cap-R-48…50)",
v.kind.label(),
v.detail
),
zh: format!(
"可综合闭包违规:{}({});SynthesizableClosure 要求纯函数、无堆、无运行时捕获状态(FR74 / Cap-R-48…50)",
v.kind.label(),
v.detail
),
});
}
diags
}
#[derive(Debug, Clone)]
pub struct GeneratedInstance {
pub name: String,
pub module: String,
pub connects: Vec<(String, String)>,
pub params: Vec<(String, u32)>,
}
impl GeneratedInstance {
pub fn new(
name: impl Into<String>,
module: impl Into<String>,
connects: Vec<(String, String)>,
params: Vec<(String, u32)>,
) -> Self {
Self {
name: name.into(),
module: module.into(),
connects,
params,
}
}
}