aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.github/issue_template.md2
-rw-r--r--Makefile2
-rw-r--r--backends/btor/btor.cc15
-rw-r--r--backends/smt2/smt2.cc12
-rw-r--r--backends/smv/smv.cc18
-rw-r--r--frontends/aiger/aigerparse.cc23
-rw-r--r--frontends/ast/simplify.cc89
-rw-r--r--frontends/verilog/verilog_lexer.l3
-rw-r--r--frontends/verilog/verilog_parser.y135
-rw-r--r--tests/various/countbits.sv69
-rw-r--r--tests/various/countbits.ys7
-rw-r--r--tests/verilog/int_types.sv47
-rw-r--r--tests/verilog/int_types.ys7
-rw-r--r--tests/verilog/param_int_types.sv19
-rw-r--r--tests/verilog/param_int_types.ys5
15 files changed, 388 insertions, 65 deletions
diff --git a/.github/issue_template.md b/.github/issue_template.md
index 5a0723c3e..c72daae3e 100644
--- a/.github/issue_template.md
+++ b/.github/issue_template.md
@@ -13,7 +13,7 @@ create a Minimal, Complete, and Verifiable example (MCVE).
Please do not waste our time with issues that lack sufficient information
to reproduce the issue easily. We will simply close those issues.
-Contact https://www.symbioticeda.com/ if you need commercial support for Yosys.
+Contact https://www.yosyshq.com/ if you need commercial support for Yosys.
## Expected behavior
diff --git a/Makefile b/Makefile
index 50f4f52b7..ced14cb48 100644
--- a/Makefile
+++ b/Makefile
@@ -126,7 +126,7 @@ LDFLAGS += -rdynamic
LDLIBS += -lrt
endif
-YOSYS_VER := 0.9+3911
+YOSYS_VER := 0.9+3962
GIT_REV := $(shell cd $(YOSYS_SRC) && git rev-parse --short HEAD 2> /dev/null || echo UNKNOWN)
OBJS = kernel/version_$(GIT_REV).o
diff --git a/backends/btor/btor.cc b/backends/btor/btor.cc
index 639c6f129..692452aad 100644
--- a/backends/btor/btor.cc
+++ b/backends/btor/btor.cc
@@ -860,7 +860,20 @@ struct BtorWorker
goto okay;
}
- log_error("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell));
+ if (cell->type.in(ID($dffe), ID($sdff), ID($sdffe), ID($sdffce)) || cell->type.str().substr(0, 6) == "$_SDFF" || (cell->type.str().substr(0, 6) == "$_DFFE" && cell->type.str().size() == 10)) {
+ log_error("Unsupported cell type %s for cell %s.%s -- please run `dffunmap` before `write_btor`.\n",
+ log_id(cell->type), log_id(module), log_id(cell));
+ }
+ if (cell->type.in(ID($adff), ID($adffe), ID($dffsr), ID($dffsre)) || cell->type.str().substr(0, 5) == "$_DFF") {
+ log_error("Unsupported cell type %s for cell %s.%s -- please run `async2sync; dffunmap` or `clk2fflogic` before `write_btor`.\n",
+ log_id(cell->type), log_id(module), log_id(cell));
+ }
+ if (cell->type.in(ID($sr), ID($dlatch), ID($adlatch), ID($dlatchsr)) || cell->type.str().substr(0, 8) == "$_DLATCH" || cell->type.str().substr(0, 5) == "$_SR_") {
+ log_error("Unsupported cell type %s for cell %s.%s -- please run `clk2fflogic` before `write_btor`.\n",
+ log_id(cell->type), log_id(module), log_id(cell));
+ }
+ log_error("Unsupported cell type %s for cell %s.%s.\n",
+ log_id(cell->type), log_id(module), log_id(cell));
okay:
btorf_pop(log_id(cell));
diff --git a/backends/smt2/smt2.cc b/backends/smt2/smt2.cc
index a185fdd74..8be9e05f1 100644
--- a/backends/smt2/smt2.cc
+++ b/backends/smt2/smt2.cc
@@ -855,6 +855,18 @@ struct Smt2Worker
return;
}
+ if (cell->type.in(ID($dffe), ID($sdff), ID($sdffe), ID($sdffce)) || cell->type.str().substr(0, 6) == "$_SDFF" || (cell->type.str().substr(0, 6) == "$_DFFE" && cell->type.str().size() == 10)) {
+ log_error("Unsupported cell type %s for cell %s.%s -- please run `dffunmap` before `write_smt2`.\n",
+ log_id(cell->type), log_id(module), log_id(cell));
+ }
+ if (cell->type.in(ID($adff), ID($adffe), ID($dffsr), ID($dffsre)) || cell->type.str().substr(0, 5) == "$_DFF") {
+ log_error("Unsupported cell type %s for cell %s.%s -- please run `async2sync; dffunmap` or `clk2fflogic` before `write_smt2`.\n",
+ log_id(cell->type), log_id(module), log_id(cell));
+ }
+ if (cell->type.in(ID($sr), ID($dlatch), ID($adlatch), ID($dlatchsr)) || cell->type.str().substr(0, 8) == "$_DLATCH" || cell->type.str().substr(0, 5) == "$_SR_") {
+ log_error("Unsupported cell type %s for cell %s.%s -- please run `clk2fflogic` before `write_smt2`.\n",
+ log_id(cell->type), log_id(module), log_id(cell));
+ }
log_error("Unsupported cell type %s for cell %s.%s.\n",
log_id(cell->type), log_id(module), log_id(cell));
}
diff --git a/backends/smv/smv.cc b/backends/smv/smv.cc
index 4e5c6050d..e41582fea 100644
--- a/backends/smv/smv.cc
+++ b/backends/smv/smv.cc
@@ -573,8 +573,22 @@ struct SmvWorker
continue;
}
- if (cell->type[0] == '$')
- log_error("Found currently unsupported cell type %s (%s.%s).\n", log_id(cell->type), log_id(module), log_id(cell));
+ if (cell->type[0] == '$') {
+ if (cell->type.in(ID($dffe), ID($sdff), ID($sdffe), ID($sdffce)) || cell->type.str().substr(0, 6) == "$_SDFF" || (cell->type.str().substr(0, 6) == "$_DFFE" && cell->type.str().size() == 10)) {
+ log_error("Unsupported cell type %s for cell %s.%s -- please run `dffunmap` before `write_smv`.\n",
+ log_id(cell->type), log_id(module), log_id(cell));
+ }
+ if (cell->type.in(ID($adff), ID($adffe), ID($dffsr), ID($dffsre)) || cell->type.str().substr(0, 5) == "$_DFF") {
+ log_error("Unsupported cell type %s for cell %s.%s -- please run `async2sync; dffunmap` or `clk2fflogic` before `write_smv`.\n",
+ log_id(cell->type), log_id(module), log_id(cell));
+ }
+ if (cell->type.in(ID($sr), ID($dlatch), ID($adlatch), ID($dlatchsr)) || cell->type.str().substr(0, 8) == "$_DLATCH" || cell->type.str().substr(0, 5) == "$_SR_") {
+ log_error("Unsupported cell type %s for cell %s.%s -- please run `clk2fflogic` before `write_smv`.\n",
+ log_id(cell->type), log_id(module), log_id(cell));
+ }
+ log_error("Unsupported cell type %s for cell %s.%s.\n",
+ log_id(cell->type), log_id(module), log_id(cell));
+ }
// f << stringf(" %s : %s;\n", cid(cell->name), cid(cell->type));
diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc
index 07e3cd6e0..463c5965b 100644
--- a/frontends/aiger/aigerparse.cc
+++ b/frontends/aiger/aigerparse.cc
@@ -55,6 +55,17 @@ inline int32_t from_big_endian(int32_t i32) {
#define log_debug2(...) ;
//#define log_debug2(...) log_debug(__VA_ARGS__)
+static int decimal_digits(uint32_t n) {
+ static uint32_t digit_cutoff[9] = {
+ 10, 100, 1000, 10000, 100000,
+ 1000000, 10000000, 100000000, 1000000000
+ };
+ for (int i = 0; i < 9; ++i) {
+ if (n < digit_cutoff[i]) return i + 1;
+ }
+ return 10;
+}
+
struct ConstEvalAig
{
RTLIL::Module *module;
@@ -515,7 +526,7 @@ void AigerReader::parse_aiger_ascii()
unsigned l1, l2, l3;
// Parse inputs
- int digits = ceil(log10(I));
+ int digits = decimal_digits(I);
for (unsigned i = 1; i <= I; ++i, ++line_count) {
if (!(f >> l1))
log_error("Line %u cannot be interpreted as an input!\n", line_count);
@@ -537,7 +548,7 @@ void AigerReader::parse_aiger_ascii()
clk_wire->port_input = true;
clk_wire->port_output = false;
}
- digits = ceil(log10(L));
+ digits = decimal_digits(L);
for (unsigned i = 0; i < L; ++i, ++line_count) {
if (!(f >> l1 >> l2))
log_error("Line %u cannot be interpreted as a latch!\n", line_count);
@@ -575,7 +586,7 @@ void AigerReader::parse_aiger_ascii()
}
// Parse outputs
- digits = ceil(log10(O));
+ digits = decimal_digits(O);
for (unsigned i = 0; i < O; ++i, ++line_count) {
if (!(f >> l1))
log_error("Line %u cannot be interpreted as an output!\n", line_count);
@@ -643,7 +654,7 @@ void AigerReader::parse_aiger_binary()
std::string line;
// Parse inputs
- int digits = ceil(log10(I));
+ int digits = decimal_digits(I);
for (unsigned i = 1; i <= I; ++i) {
log_debug2("%d is an input\n", i);
RTLIL::Wire *wire = module->addWire(stringf("$i%0*d", digits, i));
@@ -662,7 +673,7 @@ void AigerReader::parse_aiger_binary()
clk_wire->port_input = true;
clk_wire->port_output = false;
}
- digits = ceil(log10(L));
+ digits = decimal_digits(L);
l1 = (I+1) * 2;
for (unsigned i = 0; i < L; ++i, ++line_count, l1 += 2) {
if (!(f >> l2))
@@ -700,7 +711,7 @@ void AigerReader::parse_aiger_binary()
}
// Parse outputs
- digits = ceil(log10(O));
+ digits = decimal_digits(O);
for (unsigned i = 0; i < O; ++i, ++line_count) {
if (!(f >> l1))
log_error("Line %u cannot be interpreted as an output!\n", line_count);
diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc
index 6b4b9e045..5c4dd290f 100644
--- a/frontends/ast/simplify.cc
+++ b/frontends/ast/simplify.cc
@@ -571,7 +571,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
static bool deep_recursion_warning = false;
if (recursion_counter++ == 1000 && deep_recursion_warning) {
- log_warning("Deep recursion in AST simplifier.\nDoes this design contain insanely long expressions?\n");
+ log_warning("Deep recursion in AST simplifier.\nDoes this design contain overly long or deeply nested expressions, or excessive recursion?\n");
deep_recursion_warning = false;
}
@@ -3089,6 +3089,93 @@ skip_dynamic_range_lvalue_expansion:;
goto apply_newNode;
}
+ if (str == "\\$countbits") {
+ if (children.size() < 2)
+ log_file_error(filename, location.first_line, "System function %s got %d arguments, expected at least 2.\n",
+ RTLIL::unescape_id(str).c_str(), int(children.size()));
+
+ std::vector<RTLIL::State> control_bits;
+
+ // Determine which bits to count
+ for (size_t i = 1; i < children.size(); i++) {
+ AstNode *node = children[i];
+ while (node->simplify(true, false, false, stage, -1, false, false)) { }
+ if (node->type != AST_CONSTANT)
+ log_file_error(filename, location.first_line, "Failed to evaluate system function `%s' with non-constant control bit argument.\n", str.c_str());
+ if (node->bits.size() != 1)
+ log_file_error(filename, location.first_line, "Failed to evaluate system function `%s' with control bit width != 1.\n", str.c_str());
+ control_bits.push_back(node->bits[0]);
+ }
+
+ // Detect width of exp (first argument of $countbits)
+ int exp_width = -1;
+ bool exp_sign = false;
+ AstNode *exp = children[0];
+ exp->detectSignWidth(exp_width, exp_sign, NULL);
+
+ newNode = mkconst_int(0, false);
+
+ for (int i = 0; i < exp_width; i++) {
+ // Generate nodes for: exp << i >> ($size(exp) - 1)
+ // ^^ ^^
+ AstNode *lsh_node = new AstNode(AST_SHIFT_LEFT, exp->clone(), mkconst_int(i, false));
+ AstNode *rsh_node = new AstNode(AST_SHIFT_RIGHT, lsh_node, mkconst_int(exp_width - 1, false));
+
+ AstNode *or_node = nullptr;
+
+ for (RTLIL::State control_bit : control_bits) {
+ // Generate node for: (exp << i >> ($size(exp) - 1)) === control_bit
+ // ^^^
+ AstNode *eq_node = new AstNode(AST_EQX, rsh_node->clone(), mkconst_bits({control_bit}, false));
+
+ // Or the result for each checked bit value
+ if (or_node)
+ or_node = new AstNode(AST_LOGIC_OR, or_node, eq_node);
+ else
+ or_node = eq_node;
+ }
+
+ // We should have at least one element in control_bits,
+ // because we checked for the number of arguments above
+ log_assert(or_node != nullptr);
+
+ delete rsh_node;
+
+ // Generate node for adding with result of previous bit
+ newNode = new AstNode(AST_ADD, newNode, or_node);
+ }
+
+ goto apply_newNode;
+ }
+
+ if (str == "\\$countones" || str == "\\$isunknown" || str == "\\$onehot" || str == "\\$onehot0") {
+ if (children.size() != 1)
+ log_file_error(filename, location.first_line, "System function %s got %d arguments, expected 1.\n",
+ RTLIL::unescape_id(str).c_str(), int(children.size()));
+
+ AstNode *countbits = clone();
+ countbits->str = "\\$countbits";
+
+ if (str == "\\$countones") {
+ countbits->children.push_back(mkconst_bits({RTLIL::State::S1}, false));
+ newNode = countbits;
+ } else if (str == "\\$isunknown") {
+ countbits->children.push_back(mkconst_bits({RTLIL::Sx}, false));
+ countbits->children.push_back(mkconst_bits({RTLIL::Sz}, false));
+ newNode = new AstNode(AST_GT, countbits, mkconst_int(0, false));
+ } else if (str == "\\$onehot") {
+ countbits->children.push_back(mkconst_bits({RTLIL::State::S1}, false));
+ newNode = new AstNode(AST_EQ, countbits, mkconst_int(1, false));
+ } else if (str == "\\$onehot0") {
+ countbits->children.push_back(mkconst_bits({RTLIL::State::S1}, false));
+ newNode = new AstNode(AST_LE, countbits, mkconst_int(1, false));
+ } else {
+ log_abort();
+ }
+
+ goto apply_newNode;
+ }
+
if (current_scope.count(str) != 0 && current_scope[str]->type == AST_DPI_FUNCTION)
{
AstNode *dpi_decl = current_scope[str];
diff --git a/frontends/verilog/verilog_lexer.l b/frontends/verilog/verilog_lexer.l
index f2241066f..66772a097 100644
--- a/frontends/verilog/verilog_lexer.l
+++ b/frontends/verilog/verilog_lexer.l
@@ -234,7 +234,7 @@ static bool isUserType(std::string &s)
"automatic" { return TOK_AUTOMATIC; }
"unique" { SV_KEYWORD(TOK_UNIQUE); }
-"unique0" { SV_KEYWORD(TOK_UNIQUE); }
+"unique0" { SV_KEYWORD(TOK_UNIQUE0); }
"priority" { SV_KEYWORD(TOK_PRIORITY); }
"always_comb" { SV_KEYWORD(TOK_ALWAYS_COMB); }
@@ -267,6 +267,7 @@ static bool isUserType(std::string &s)
"int" { SV_KEYWORD(TOK_INT); }
"byte" { SV_KEYWORD(TOK_BYTE); }
"shortint" { SV_KEYWORD(TOK_SHORTINT); }
+"longint" { SV_KEYWORD(TOK_LONGINT); }
"eventually" { if (formal_mode) return TOK_EVENTUALLY; SV_KEYWORD(TOK_EVENTUALLY); }
"s_eventually" { if (formal_mode) return TOK_EVENTUALLY; SV_KEYWORD(TOK_EVENTUALLY); }
diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y
index 89e686818..476ee68ad 100644
--- a/frontends/verilog/verilog_parser.y
+++ b/frontends/verilog/verilog_parser.y
@@ -253,6 +253,7 @@ static void rewriteAsMemoryNode(AstNode *node, AstNode *rangeNode)
struct specify_rise_fall *specify_rise_fall_ptr;
bool boolean;
char ch;
+ int integer;
}
%token <string> TOK_STRING TOK_ID TOK_CONSTVAL TOK_REALVAL TOK_PRIMITIVE
@@ -277,16 +278,18 @@ static void rewriteAsMemoryNode(AstNode *node, AstNode *rangeNode)
%token TOK_SUPPLY0 TOK_SUPPLY1 TOK_TO_SIGNED TOK_TO_UNSIGNED
%token TOK_POS_INDEXED TOK_NEG_INDEXED TOK_PROPERTY TOK_ENUM TOK_TYPEDEF
%token TOK_RAND TOK_CONST TOK_CHECKER TOK_ENDCHECKER TOK_EVENTUALLY
-%token TOK_INCREMENT TOK_DECREMENT TOK_UNIQUE TOK_PRIORITY
-%token TOK_STRUCT TOK_PACKED TOK_UNSIGNED TOK_INT TOK_BYTE TOK_SHORTINT TOK_UNION
+%token TOK_INCREMENT TOK_DECREMENT TOK_UNIQUE TOK_UNIQUE0 TOK_PRIORITY
+%token TOK_STRUCT TOK_PACKED TOK_UNSIGNED TOK_INT TOK_BYTE TOK_SHORTINT TOK_LONGINT TOK_UNION
%token TOK_OR_ASSIGN TOK_XOR_ASSIGN TOK_AND_ASSIGN TOK_SUB_ASSIGN
-%type <ast> range range_or_multirange non_opt_range non_opt_multirange range_or_signed_int
+%type <ast> range range_or_multirange non_opt_range non_opt_multirange
%type <ast> wire_type expr basic_expr concat_list rvalue lvalue lvalue_concat_list non_io_wire_type io_wire_type
%type <string> opt_label opt_sva_label tok_prim_wrapper hierarchical_id hierarchical_type_id integral_number
%type <string> type_name
-%type <ast> opt_enum_init enum_type struct_type non_wire_data_type
-%type <boolean> opt_signed opt_property unique_case_attr always_comb_or_latch always_or_always_ff
+%type <ast> opt_enum_init enum_type struct_type non_wire_data_type func_return_type
+%type <boolean> opt_property always_comb_or_latch always_or_always_ff
+%type <boolean> opt_signedness_default_signed opt_signedness_default_unsigned
+%type <integer> integer_atom_type
%type <al> attr case_attr
%type <ast> struct_union
@@ -716,12 +719,19 @@ wire_type_token:
logic_type:
TOK_LOGIC {
} |
- TOK_INTEGER {
- astbuf3->range_left = 31;
+ integer_atom_type {
+ astbuf3->range_left = $1 - 1;
astbuf3->range_right = 0;
astbuf3->is_signed = true;
};
+integer_atom_type:
+ TOK_INTEGER { $$ = 32; } |
+ TOK_INT { $$ = 32; } |
+ TOK_SHORTINT { $$ = 16; } |
+ TOK_LONGINT { $$ = 64; } |
+ TOK_BYTE { $$ = 8; } ;
+
non_opt_range:
'[' expr ':' expr ']' {
$$ = new AstNode(AST_RANGE);
@@ -766,11 +776,6 @@ range_or_multirange:
range { $$ = $1; } |
non_opt_multirange { $$ = $1; };
-range_or_signed_int:
- range { $$ = $1; }
- | TOK_INTEGER { $$ = makeRange(); }
- ;
-
module_body:
module_body module_body_stmt |
/* the following line makes the generate..endgenrate keywords optional */
@@ -841,29 +846,58 @@ task_func_decl:
current_function_or_task = NULL;
ast_stack.pop_back();
} |
- attr TOK_FUNCTION opt_automatic opt_signed range_or_signed_int TOK_ID {
+ attr TOK_FUNCTION opt_automatic func_return_type TOK_ID {
current_function_or_task = new AstNode(AST_FUNCTION);
- current_function_or_task->str = *$6;
+ current_function_or_task->str = *$5;
append_attr(current_function_or_task, $1);
ast_stack.back()->children.push_back(current_function_or_task);
ast_stack.push_back(current_function_or_task);
AstNode *outreg = new AstNode(AST_WIRE);
- outreg->str = *$6;
- outreg->is_signed = $4;
+ outreg->str = *$5;
+ outreg->is_signed = false;
outreg->is_reg = true;
- if ($5 != NULL) {
- outreg->children.push_back($5);
- outreg->is_signed = $4 || $5->is_signed;
- $5->is_signed = false;
+ if ($4 != NULL) {
+ outreg->children.push_back($4);
+ outreg->is_signed = $4->is_signed;
+ $4->is_signed = false;
}
current_function_or_task->children.push_back(outreg);
current_function_or_task_port_id = 1;
- delete $6;
+ delete $5;
} task_func_args_opt ';' task_func_body TOK_ENDFUNCTION {
current_function_or_task = NULL;
ast_stack.pop_back();
};
+func_return_type:
+ opt_type_vec opt_signedness_default_unsigned {
+ $$ = makeRange(0, 0, $2);
+ } |
+ opt_type_vec opt_signedness_default_unsigned non_opt_range {
+ $$ = $3;
+ $$->is_signed = $2;
+ } |
+ integer_atom_type opt_signedness_default_signed {
+ $$ = makeRange($1 - 1, 0, $2);
+ };
+
+opt_type_vec:
+ %empty
+ | TOK_REG
+ | TOK_LOGIC
+ ;
+
+opt_signedness_default_signed:
+ %empty { $$ = true; }
+ | TOK_SIGNED { $$ = true; }
+ | TOK_UNSIGNED { $$ = false; }
+ ;
+opt_signedness_default_unsigned:
+ %empty { $$ = false; }
+ | TOK_SIGNED { $$ = true; }
+ | TOK_UNSIGNED { $$ = false; }
+ ;
+
dpi_function_arg:
TOK_ID TOK_ID {
current_function_or_task->children.push_back(AstNode::mkconst_str(*$1));
@@ -889,14 +923,6 @@ opt_automatic:
TOK_AUTOMATIC |
%empty;
-opt_signed:
- TOK_SIGNED {
- $$ = true;
- } |
- %empty {
- $$ = false;
- };
-
task_func_args_opt:
'(' ')' | %empty | '(' {
albuf = nullptr;
@@ -1379,11 +1405,8 @@ param_signed:
} | %empty;
param_integer:
- TOK_INTEGER {
- astbuf1->children.push_back(new AstNode(AST_RANGE));
- astbuf1->children.back()->children.push_back(AstNode::mkconst_int(31, true));
- astbuf1->children.back()->children.push_back(AstNode::mkconst_int(0, true));
- astbuf1->is_signed = true;
+ type_atom {
+ astbuf1->is_reg = false;
};
param_real:
@@ -1399,7 +1422,13 @@ param_range:
};
param_integer_type: param_integer param_signed;
-param_range_type: type_vec param_signed param_range;
+param_range_type:
+ type_vec param_signed {
+ addRange(astbuf1, 0, 0);
+ } |
+ type_vec param_signed non_opt_range {
+ astbuf1->children.push_back($3);
+ };
param_implicit_type: param_signed param_range;
param_type:
@@ -1496,11 +1525,12 @@ enum_base_type: type_atom type_signing
| %empty { astbuf1->is_reg = true; addRange(astbuf1); }
;
-type_atom: TOK_INTEGER { astbuf1->is_reg = true; astbuf1->is_signed = true; addRange(astbuf1); } // 4-state signed
- | TOK_INT { astbuf1->is_reg = true; astbuf1->is_signed = true; addRange(astbuf1); } // 2-state signed
- | TOK_SHORTINT { astbuf1->is_reg = true; astbuf1->is_signed = true; addRange(astbuf1, 15, 0); } // 2-state signed
- | TOK_BYTE { astbuf1->is_reg = true; astbuf1->is_signed = true; addRange(astbuf1, 7, 0); } // 2-state signed
- ;
+type_atom:
+ integer_atom_type {
+ astbuf1->is_reg = true;
+ astbuf1->is_signed = true;
+ addRange(astbuf1, $1 - 1, 0);
+ };
type_vec: TOK_REG { astbuf1->is_reg = true; } // unsigned
| TOK_LOGIC { astbuf1->is_logic = true; } // unsigned
@@ -2559,20 +2589,21 @@ behavioral_stmt:
ast_stack.pop_back();
};
-unique_case_attr:
- %empty {
- $$ = false;
+case_attr:
+ attr {
+ $$ = $1;
} |
- TOK_PRIORITY case_attr {
- $$ = $2;
+ attr TOK_UNIQUE0 {
+ (*$1)[ID::parallel_case] = AstNode::mkconst_int(1, false);
+ $$ = $1;
} |
- TOK_UNIQUE case_attr {
- $$ = true;
- };
-
-case_attr:
- attr unique_case_attr {
- if ($2) (*$1)[ID::parallel_case] = AstNode::mkconst_int(1, false);
+ attr TOK_PRIORITY {
+ (*$1)[ID::full_case] = AstNode::mkconst_int(1, false);
+ $$ = $1;
+ } |
+ attr TOK_UNIQUE {
+ (*$1)[ID::full_case] = AstNode::mkconst_int(1, false);
+ (*$1)[ID::parallel_case] = AstNode::mkconst_int(1, false);
$$ = $1;
};
diff --git a/tests/various/countbits.sv b/tests/various/countbits.sv
new file mode 100644
index 000000000..5762217bb
--- /dev/null
+++ b/tests/various/countbits.sv
@@ -0,0 +1,69 @@
+module top;
+
+ assert property ($countbits(15'b011xxxxzzzzzzzz, '0 ) == 1);
+ assert property ($countbits(15'b011xxxxzzzzzzzz, '1 ) == 2);
+ assert property ($countbits(15'b011xxxxzzzzzzzz, 'x ) == 4);
+ assert property ($countbits(15'b011xxxxzzzzzzzz, 'z ) == 8);
+ assert property ($countbits(15'b011xxxxzzzzzzzz, '0, '1 ) == 3);
+ assert property ($countbits(15'b011xxxxzzzzzzzz, '1, '1, '0 ) == 3);
+ assert property ($countbits(15'b011xxxxzzzzzzzz, '0, 'x ) == 5);
+ assert property ($countbits(15'b011xxxxzzzzzzzz, '0, 'z ) == 9);
+ assert property ($countbits(15'bz1x10xzxzzxzzzz, '0, 'z ) == 9);
+ assert property ($countbits(15'b011xxxxzzzzzzzz, 'x, 'z ) == 12);
+ assert property ($countbits(15'b011xxxxzzzzzzzz, '1, 'z ) == 10);
+ assert property ($countbits(15'b011xxxxzzzzzzzz, '1, 'x, 'z ) == 14);
+ assert property ($countbits(15'b011xxxxzzzzzzzz, '1, 'x, 'z, '0) == 15);
+
+ assert property ($countbits(0, '0) == 32); // test integers
+ assert property ($countbits(0, '1) == 0);
+ assert property ($countbits(80'b0, '0) == 80); // test something bigger than integer
+ assert property ($countbits(80'bx0, 'x) == 79);
+
+ always_comb begin
+ logic one;
+ logic [1:0] two;
+ logic [3:0] four;
+
+ // Make sure that the width of the whole expression doesn't affect the width of the shift
+ // operations inside the function.
+ one = $countbits(3'b100, '1) & 1'b1;
+ two = $countbits(3'b111, '1) & 2'b11;
+ four = $countbits(3'b111, '1) & 4'b1111;
+
+ assert (one == 1);
+ assert (two == 3);
+ assert (four == 3);
+ end
+
+ assert property ($countones(8'h00) == 0);
+ assert property ($countones(8'hff) == 8);
+ assert property ($countones(8'ha5) == 4);
+ assert property ($countones(8'h13) == 3);
+
+ logic test1 = 1'b1;
+ logic [4:0] test5 = 5'b10101;
+
+ assert property ($countones(test1) == 1);
+ assert property ($countones(test5) == 3);
+
+ assert property ($isunknown(8'h00) == 0);
+ assert property ($isunknown(8'hff) == 0);
+ assert property ($isunknown(8'hx0) == 1);
+ assert property ($isunknown(8'h1z) == 1);
+ assert property ($isunknown(8'hxz) == 1);
+
+ assert property ($onehot(8'h00) == 0);
+ assert property ($onehot(8'hff) == 0);
+ assert property ($onehot(8'h01) == 1);
+ assert property ($onehot(8'h80) == 1);
+ assert property ($onehot(8'h81) == 0);
+ assert property ($onehot(8'h20) == 1);
+
+ assert property ($onehot0(8'h00) == 1);
+ assert property ($onehot0(8'hff) == 0);
+ assert property ($onehot0(8'h01) == 1);
+ assert property ($onehot0(8'h80) == 1);
+ assert property ($onehot0(8'h81) == 0);
+ assert property ($onehot0(8'h20) == 1);
+
+endmodule
diff --git a/tests/various/countbits.ys b/tests/various/countbits.ys
new file mode 100644
index 000000000..a556f7c5d
--- /dev/null
+++ b/tests/various/countbits.ys
@@ -0,0 +1,7 @@
+read_verilog -sv countbits.sv
+hierarchy
+proc
+flatten
+opt -full
+select -module top
+sat -verify -seq 1 -tempinduct -prove-asserts -show-all
diff --git a/tests/verilog/int_types.sv b/tests/verilog/int_types.sv
new file mode 100644
index 000000000..8133f8218
--- /dev/null
+++ b/tests/verilog/int_types.sv
@@ -0,0 +1,47 @@
+`define TEST(typ, width, is_signed) \
+ if (1) begin \
+ typ x = -1; \
+ localparam typ y = -1; \
+ logic [127:0] a = x; \
+ logic [127:0] b = y; \
+ if ($bits(x) != width) \
+ $error(`"typ doesn't have expected size width`"); \
+ if ($bits(x) != $bits(y)) \
+ $error(`"localparam typ doesn't match size of typ`"); \
+ function automatic typ f; \
+ input integer x; \
+ f = x; \
+ endfunction \
+ logic [127:0] c = f(-1); \
+ always @* begin \
+ assert (x == y); \
+ assert (a == b); \
+ assert (a == c); \
+ assert ((a == -1) == is_signed); \
+ end \
+ end
+
+`define TEST_INTEGER_ATOM(typ, width) \
+ `TEST(typ, width, 1) \
+ `TEST(typ signed, width, 1) \
+ `TEST(typ unsigned, width, 0)
+
+`define TEST_INTEGER_VECTOR(typ) \
+ `TEST(typ, 1, 0) \
+ `TEST(typ signed, 1, 1) \
+ `TEST(typ unsigned, 1, 0) \
+ `TEST(typ [1:0], 2, 0) \
+ `TEST(typ signed [1:0], 2, 1) \
+ `TEST(typ unsigned [1:0], 2, 0)
+
+module top;
+ `TEST_INTEGER_ATOM(integer, 32)
+ `TEST_INTEGER_ATOM(int, 32)
+ `TEST_INTEGER_ATOM(shortint, 16)
+ `TEST_INTEGER_ATOM(longint, 64)
+ `TEST_INTEGER_ATOM(byte, 8)
+
+ `TEST_INTEGER_VECTOR(reg)
+ `TEST_INTEGER_VECTOR(logic)
+ `TEST_INTEGER_VECTOR(bit)
+endmodule
diff --git a/tests/verilog/int_types.ys b/tests/verilog/int_types.ys
new file mode 100644
index 000000000..c17c44b4c
--- /dev/null
+++ b/tests/verilog/int_types.ys
@@ -0,0 +1,7 @@
+read_verilog -sv int_types.sv
+hierarchy
+proc
+flatten
+opt -full
+select -module top
+sat -verify -seq 1 -tempinduct -prove-asserts -show-all
diff --git a/tests/verilog/param_int_types.sv b/tests/verilog/param_int_types.sv
new file mode 100644
index 000000000..3228369b8
--- /dev/null
+++ b/tests/verilog/param_int_types.sv
@@ -0,0 +1,19 @@
+module gate(out);
+ parameter integer a = -1;
+ parameter int b = -2;
+ parameter shortint c = -3;
+ parameter longint d = -4;
+ parameter byte e = -5;
+ output wire [1023:0] out;
+ assign out = {a, b, c, d, e};
+endmodule
+
+module gold(out);
+ integer a = -1;
+ int b = -2;
+ shortint c = -3;
+ longint d = -4;
+ byte e = -5;
+ output wire [1023:0] out;
+ assign out = {a, b, c, d, e};
+endmodule
diff --git a/tests/verilog/param_int_types.ys b/tests/verilog/param_int_types.ys
new file mode 100644
index 000000000..7727801cf
--- /dev/null
+++ b/tests/verilog/param_int_types.ys
@@ -0,0 +1,5 @@
+read_verilog -sv param_int_types.sv
+proc
+equiv_make gold gate equiv
+equiv_simple
+equiv_status -assert