Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
794 changes: 17 additions & 777 deletions xlsynth-vastly/src/combo_compile.rs

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions xlsynth-vastly/src/combo_eval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -782,6 +782,7 @@ fn function_return_decl(f: &ComboFunction) -> crate::module_compile::DeclInfo {
width: f.ret_width,
signedness: f.ret_signedness,
packed_dims: vec![f.ret_width],
unpacked_dims: vec![],
}
}

Expand Down Expand Up @@ -979,6 +980,7 @@ fn init_function_env(f: &ComboFunction, args: &[Value4], globals: &Env) -> Env {
width: arg.width,
signedness: arg.signedness,
packed_dims: vec![arg.width],
unpacked_dims: vec![],
};
env.insert(arg.name.clone(), coerce_to_declinfo(av, &info));
}
Expand All @@ -1004,6 +1006,7 @@ fn function_target_decl(f: &ComboFunction, lhs: &str) -> Option<crate::module_co
width: a.width,
signedness: a.signedness,
packed_dims: vec![a.width],
unpacked_dims: vec![],
})
}

Expand Down
3 changes: 3 additions & 0 deletions xlsynth-vastly/src/module_compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ pub struct DeclInfo {
pub width: u32,
pub signedness: Signedness,
pub packed_dims: Vec<u32>,
pub unpacked_dims: Vec<u32>,
}

pub fn compile_module(src: &str) -> Result<CompiledModule> {
Expand All @@ -42,6 +43,7 @@ pub fn compile_module(src: &str) -> Result<CompiledModule> {
signed,
width,
packed_dims,
unpacked_dims,
} in m.decls.clone()
{
let signedness = if signed {
Expand All @@ -55,6 +57,7 @@ pub fn compile_module(src: &str) -> Result<CompiledModule> {
width,
signedness,
packed_dims,
unpacked_dims,
},
);
}
Expand Down
51 changes: 27 additions & 24 deletions xlsynth-vastly/src/packed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,13 @@ fn remaining_width_after(dims: &[u32], consumed_indices: usize) -> Result<u32> {
}
}

fn selection_dims(info: &DeclInfo) -> Vec<u32> {
let mut dims = Vec::with_capacity(info.unpacked_dims.len() + info.packed_dims.len());
dims.extend_from_slice(&info.unpacked_dims);
dims.extend_from_slice(&info.packed_dims);
dims
}

fn build_linear_index<T: Clone, FMul, FAdd>(
indices: &[T],
packed_dims: &[u32],
Expand Down Expand Up @@ -205,13 +212,12 @@ fn lower_expr_index_chain(
if indices.is_empty() {
return Ok(None);
}
if indices.len() > info.packed_dims.len() {
return Err(Error::Parse(format!(
"too many packed indices for `{base_name}`"
)));
let dims = selection_dims(info);
if indices.len() > dims.len() {
return Err(Error::Parse(format!("too many indices for `{base_name}`")));
}
let linear_index = build_linear_index(&indices, &info.packed_dims, mul_expr, add_expr)?;
let remaining_width = remaining_width_after(&info.packed_dims, indices.len())?;
let linear_index = build_linear_index(&indices, &dims, mul_expr, add_expr)?;
let remaining_width = remaining_width_after(&dims, indices.len())?;
let base_expr = Expr::Ident(base_name.to_string());
if remaining_width == 1 {
Ok(Some(Expr::Index {
Expand Down Expand Up @@ -243,18 +249,17 @@ fn lower_spanned_index_chain(
if indices.is_empty() {
return Ok(None);
}
if indices.len() > info.packed_dims.len() {
return Err(Error::Parse(format!(
"too many packed indices for `{base_name}`"
)));
let dims = selection_dims(info);
if indices.len() > dims.len() {
return Err(Error::Parse(format!("too many indices for `{base_name}`")));
}
let linear_index = build_linear_index(
&indices,
&info.packed_dims,
&dims,
|index, stride| mul_expr_spanned(index, stride, expr_span),
|lhs, rhs| add_expr_spanned(lhs, rhs, expr_span),
)?;
let remaining_width = remaining_width_after(&info.packed_dims, indices.len())?;
let remaining_width = remaining_width_after(&dims, indices.len())?;
if remaining_width == 1 {
Ok(Some(SpannedExpr {
span: expr_span,
Expand Down Expand Up @@ -528,13 +533,12 @@ pub fn packed_index_selection(info: &DeclInfo, indices: &[u32]) -> Result<(u32,
if indices.is_empty() {
return Ok((0, info.width));
}
if indices.len() > info.packed_dims.len() {
return Err(Error::Parse(
"too many packed indices for declaration".to_string(),
));
let dims = selection_dims(info);
if indices.len() > dims.len() {
return Err(Error::Parse("too many indices for declaration".to_string()));
}
let offset = checked_packed_offset(&info.packed_dims, indices)?;
let width = remaining_width_after(&info.packed_dims, indices.len())?;
let offset = checked_packed_offset(&dims, indices)?;
let width = remaining_width_after(&dims, indices.len())?;
Ok((offset, width))
}

Expand All @@ -545,14 +549,13 @@ pub fn packed_index_selection_if_in_bounds(
if indices.is_empty() {
return Ok(Some((0, info.width)));
}
if indices.len() > info.packed_dims.len() {
return Err(Error::Parse(
"too many packed indices for declaration".to_string(),
));
let dims = selection_dims(info);
if indices.len() > dims.len() {
return Err(Error::Parse("too many indices for declaration".to_string()));
}
let Some(offset) = checked_packed_offset_if_in_bounds(&info.packed_dims, indices)? else {
let Some(offset) = checked_packed_offset_if_in_bounds(&dims, indices)? else {
return Ok(None);
};
let width = remaining_width_after(&info.packed_dims, indices.len())?;
let width = remaining_width_after(&dims, indices.len())?;
Ok(Some((offset, width)))
}
22 changes: 14 additions & 8 deletions xlsynth-vastly/src/pipeline_compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,14 @@ pub fn compile_pipeline_module_with_defines(
src: &str,
defines: &BTreeSet<String>,
) -> Result<CompiledPipelineModule> {
let parse_src = src;
let parsed: PipelineModule =
crate::sv_parser::parse_pipeline_module_with_defines(src, defines)?;
let items =
crate::generate_constructs::elaborate_pipeline_items(src, &parsed.params, &parsed.items)?;
crate::sv_parser::parse_pipeline_module_with_defines(parse_src, defines)?;
let items = crate::generate_constructs::elaborate_pipeline_items(
parse_src,
&parsed.params,
&parsed.items,
)?;

let module_name = parsed.name.clone();

Expand Down Expand Up @@ -147,7 +151,7 @@ pub fn compile_pipeline_module_with_defines(
} => {
let rhs_src = rhs_text
.as_deref()
.unwrap_or_else(|| src[rhs.start..rhs.end].trim());
.unwrap_or_else(|| parse_src[rhs.start..rhs.end].trim());
let lhs = rewrite_packed_lhs(lhs.clone(), &decls)?;
let rhs_expr = rewrite_packed_expr(crate::parser::parse_expr(rhs_src)?, &decls)?;
let mut rhs_spanned = crate::parser_spanned::parse_expr_spanned(rhs_src)?;
Expand Down Expand Up @@ -204,15 +208,15 @@ pub fn compile_pipeline_module_with_defines(

let body = match &f.body {
crate::sv_ast::ComboFunctionBody::UniqueCasez { selector, arms, .. } => {
let selector_src = src[selector.start..selector.end].trim();
let selector_src = parse_src[selector.start..selector.end].trim();
let selector_expr = rewrite_packed_expr(
crate::parser::parse_expr(selector_src)?,
&fn_decls,
)?;

let mut out_arms: Vec<CasezArm> = Vec::new();
for a in arms {
let value_src = src[a.value.start..a.value.end].trim();
let value_src = parse_src[a.value.start..a.value.end].trim();
let value_expr = rewrite_packed_expr(
crate::parser::parse_expr(value_src)?,
&fn_decls,
Expand All @@ -232,7 +236,7 @@ pub fn compile_pipeline_module_with_defines(
}
}
crate::sv_ast::ComboFunctionBody::Assign { value } => {
let value_src = src[value.start..value.end].trim();
let value_src = parse_src[value.start..value.end].trim();
let expr =
rewrite_packed_expr(crate::parser::parse_expr(value_src)?, &fn_decls)?;
let mut expr_spanned =
Expand All @@ -248,7 +252,7 @@ pub fn compile_pipeline_module_with_defines(
let mut out_assigns: Vec<FunctionAssign> =
Vec::with_capacity(assigns.len());
for a in assigns {
let value_src = src[a.value.start..a.value.end].trim();
let value_src = parse_src[a.value.start..a.value.end].trim();
let expr = rewrite_packed_expr(
crate::parser::parse_expr(value_src)?,
&fn_decls,
Expand Down Expand Up @@ -506,6 +510,7 @@ fn decl_info_from_decl(d: &crate::sv_ast::Decl) -> DeclInfo {
Signedness::Unsigned
},
packed_dims: d.packed_dims.clone(),
unpacked_dims: d.unpacked_dims.clone(),
}
}

Expand All @@ -518,6 +523,7 @@ fn decl_info_from_port_decl(p: &crate::sv_ast::PortDecl) -> DeclInfo {
Signedness::Unsigned
},
packed_dims: p.packed_dims.clone(),
unpacked_dims: p.unpacked_dims.clone(),
}
}

Expand Down
2 changes: 2 additions & 0 deletions xlsynth-vastly/src/sv_ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ pub struct PortDecl {
pub signed: bool,
pub width: u32,
pub packed_dims: Vec<u32>,
pub unpacked_dims: Vec<u32>,
pub name: String,
}

Expand Down Expand Up @@ -128,6 +129,7 @@ pub struct Decl {
pub signed: bool,
pub width: u32,
pub packed_dims: Vec<u32>,
pub unpacked_dims: Vec<u32>,
}

#[derive(Debug, Clone, PartialEq, Eq)]
Expand Down
57 changes: 57 additions & 0 deletions xlsynth-vastly/src/sv_parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -900,12 +900,15 @@ impl<'a> Parser<'a> {
}
_ => return Err(Error::Parse("expected port identifier".to_string())),
};
let unpacked_dims = self.parse_unpacked_dims()?;
let width = dims_total_width(width, &unpacked_dims)?;

decls.push(Decl {
name,
signed,
width,
packed_dims,
unpacked_dims,
});

match self.cur() {
Expand Down Expand Up @@ -978,13 +981,16 @@ impl<'a> Parser<'a> {
}
_ => return Err(Error::Parse("expected port identifier".to_string())),
};
let unpacked_dims = self.parse_unpacked_dims()?;
let width = dims_total_width(width, &unpacked_dims)?;

ports.push(PortDecl {
dir,
ty,
signed,
width,
packed_dims,
unpacked_dims,
name,
});

Expand All @@ -1010,6 +1016,11 @@ impl<'a> Parser<'a> {
self.expect(TokKind::RBracket)?;
let msb = self.eval_const_u32(&msb_expr)?;
let lsb = self.eval_const_u32(&lsb_expr)?;
if lsb != 0 {
return Err(Error::Parse(
"packed declaration ranges must be zero-based `[N:0]`".to_string(),
));
}
if msb < lsb {
return Err(Error::Parse("decl range msb<lsb not supported".to_string()));
}
Expand All @@ -1021,6 +1032,36 @@ impl<'a> Parser<'a> {
Ok(dims)
}

fn parse_unpacked_dims(&mut self) -> Result<Vec<u32>> {
let mut dims: Vec<u32> = Vec::new();
while *self.cur() == TokKind::LBracket {
self.bump();
let first = self.parse_expr_until(&[TokKind::Colon, TokKind::RBracket])?;
let dim = if *self.cur() == TokKind::Colon {
self.bump();
let second = self.parse_expr_until(&[TokKind::RBracket])?;
let first_u = self.eval_const_u32(&first)?;
let second_u = self.eval_const_u32(&second)?;
if second_u != 0 {
return Err(Error::Parse(
"unpacked declaration ranges must be zero-based `[N:0]`".to_string(),
));
}
first_u + 1
} else {
self.eval_const_u32(&first)?
};
self.expect(TokKind::RBracket)?;
if dim == 0 {
return Err(Error::Parse(
"unpacked array dimension must be > 0".to_string(),
));
}
dims.push(dim);
}
Ok(dims)
}

fn parse_wire_decl(&mut self) -> Result<Decl> {
let (d, _span) = self.parse_wire_decl_with_span()?;
Ok(d)
Expand All @@ -1047,6 +1088,8 @@ impl<'a> Parser<'a> {
}
_ => return Err(Error::Parse("expected identifier in wire decl".to_string())),
};
let unpacked_dims = self.parse_unpacked_dims()?;
let width = dims_total_width(width, &unpacked_dims)?;
self.expect(TokKind::Semi)?;
let end = self.toks[self.idx - 1].end;
Ok((
Expand All @@ -1055,6 +1098,7 @@ impl<'a> Parser<'a> {
signed,
width,
packed_dims,
unpacked_dims,
},
Span { start, end },
))
Expand Down Expand Up @@ -1271,6 +1315,8 @@ impl<'a> Parser<'a> {
}
_ => return Err(Error::Parse("expected identifier in decl".to_string())),
};
let unpacked_dims = self.parse_unpacked_dims()?;
let width = dims_total_width(width, &unpacked_dims)?;
if expect_semi {
self.expect(TokKind::Semi)?;
}
Expand All @@ -1279,6 +1325,7 @@ impl<'a> Parser<'a> {
signed,
width,
packed_dims,
unpacked_dims,
})
}

Expand Down Expand Up @@ -1418,12 +1465,15 @@ impl<'a> Parser<'a> {
}
_ => return Err(Error::Parse("expected identifier in decl".to_string())),
};
let unpacked_dims = self.parse_unpacked_dims()?;
let width = dims_total_width(width, &unpacked_dims)?;
self.expect(TokKind::Semi)?;
Ok(Decl {
name,
signed,
width,
packed_dims,
unpacked_dims,
})
}

Expand Down Expand Up @@ -1693,6 +1743,13 @@ fn packed_dims_width(dims: &[u32]) -> Result<u32> {
})
}

fn dims_total_width(packed_width: u32, unpacked_dims: &[u32]) -> Result<u32> {
unpacked_dims.iter().try_fold(packed_width, |acc, dim| {
acc.checked_mul(*dim)
.ok_or_else(|| Error::Parse("packed decl width overflow".to_string()))
})
}

fn parse_display_call(s: &str) -> Result<(String, Vec<VExpr>)> {
// Very small `$display` parser for forms like:
// $display("foo %d", expr, expr2)
Expand Down
Loading
Loading