From e0d3977e19342118a6e71f52c6731adad7e64cb9 Mon Sep 17 00:00:00 2001 From: Dag Lem Date: Thu, 28 Dec 2023 00:23:59 +0100 Subject: [PATCH] Add support for $dimensions and $unpacked_dimensions --- frontends/ast/simplify.cc | 19 ++++++++++++++++--- tests/sat/sizebits.sv | 18 ++++++++++++++++++ tests/svtypes/struct_sizebits.sv | 12 ++++++++++++ 3 files changed, 46 insertions(+), 3 deletions(-) diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 7486f676e..04d9af4d1 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -3487,10 +3487,11 @@ skip_dynamic_range_lvalue_expansion:; goto apply_newNode; } - if (str == "\\$increment" || str == "\\$size" || str == "\\$bits" || str == "\\$high" || str == "\\$low" || str == "\\$left" || str == "\\$right") + if (str == "\\$dimensions" || str == "\\$unpacked_dimensions" || + str == "\\$increment" || str == "\\$size" || str == "\\$bits" || str == "\\$high" || str == "\\$low" || str == "\\$left" || str == "\\$right") { int dim = 1; - if (str == "\\$bits") { + if (str == "\\$dimensions" || str == "\\$unpacked_dimensions" || str == "\\$bits") { if (children.size() != 1) input_error("System function %s got %d arguments, expected 1.\n", RTLIL::unescape_id(str).c_str(), int(children.size())); @@ -3509,6 +3510,7 @@ skip_dynamic_range_lvalue_expansion:; AstNode *buf = children[0]->clone(); int mem_depth = 1; int result, high = 0, low = 0, left = 0, right = 0, width = 1; // defaults for a simple wire + int expr_dimensions = 0, expr_unpacked_dimensions = 0; AstNode *id_ast = NULL; buf->detectSignWidth(width_hint, sign_hint); @@ -3534,6 +3536,10 @@ skip_dynamic_range_lvalue_expansion:; // or if the second argument is out of range, then 'x shall be returned." if (dim < 1 || dim > dims) input_error("Dimension %d out of range in `%s', as it only has %d dimensions!\n", dim, id_ast->str.c_str(), dims); + + expr_dimensions = dims - dim + 1; + expr_unpacked_dimensions = std::max(id_ast->unpacked_dimensions - dim + 1, 0); + right = low = id_ast->dimensions[dim - 1].range_right; left = high = low + id_ast->dimensions[dim - 1].range_width - 1; if (id_ast->dimensions[dim - 1].range_swapped) { @@ -3546,9 +3552,16 @@ skip_dynamic_range_lvalue_expansion:; width = high - low + 1; } else { width = width_hint; + right = low = 0; + left = high = width - 1; + expr_dimensions = 1; } delete buf; - if (str == "\\$high") + if (str == "\\$dimensions") + result = expr_dimensions; + else if (str == "\\$unpacked_dimensions") + result = expr_unpacked_dimensions; + else if (str == "\\$high") result = high; else if (str == "\\$low") result = low; diff --git a/tests/sat/sizebits.sv b/tests/sat/sizebits.sv index a31cae78c..a28f7ebb2 100644 --- a/tests/sat/sizebits.sv +++ b/tests/sat/sizebits.sv @@ -10,6 +10,24 @@ wire [3:0]z[7:2][2:9]; //wire [$size(y)-1:0]y_size; //wire [$size(z)-1:0]z_size; +assert property ($dimensions(t) == 1); +assert property ($dimensions(x) == 1); +assert property ($dimensions({3{x}}) == 1); +assert property ($dimensions(y) == 2); +assert property ($dimensions(y[2]) == 1); +assert property ($dimensions(z) == 3); +assert property ($dimensions(z[3]) == 2); +assert property ($dimensions(z[3][3]) == 1); + +assert property ($unpacked_dimensions(t) == 0); +assert property ($unpacked_dimensions(x) == 0); +assert property ($unpacked_dimensions({3{x}}) == 0); +assert property ($unpacked_dimensions(y) == 1); +assert property ($unpacked_dimensions(y[2]) == 0); +assert property ($unpacked_dimensions(z) == 2); +assert property ($unpacked_dimensions(z[3]) == 1); +assert property ($unpacked_dimensions(z[3][3]) == 0); + assert property ($size(t) == 1); assert property ($size(x) == 4); assert property ($size({3{x}}) == 3*4); diff --git a/tests/svtypes/struct_sizebits.sv b/tests/svtypes/struct_sizebits.sv index 7f33fe72c..0a94d57a5 100644 --- a/tests/svtypes/struct_sizebits.sv +++ b/tests/svtypes/struct_sizebits.sv @@ -25,6 +25,18 @@ struct packed { //wire [$bits({s.x, s.x})-1:0]xx_bits; always_comb begin + assert ($dimensions(s) == 1); + assert ($dimensions(s.t) == 1); + assert ($dimensions(s.x) == 1); +`ifndef VERIFIC + assert ($dimensions({3{s.x}}) == 1); +`endif + assert ($dimensions(s.sy.y) == 2); + assert ($dimensions(s.sy.y[2]) == 1); + assert ($dimensions(s.sz.z) == 3); + assert ($dimensions(s.sz.z[3]) == 2); + assert ($dimensions(s.sz.z[3][3]) == 1); + assert ($size(s) == $size(s.t) + $size(s.x) + $size(s.sy) + $size(s.sz)); assert ($size(s) == 1 + 4 + 6*4 + 6*8*4);