Merge branch 'master' of github.com:steveicarus/iverilog
This commit is contained in:
commit
5cd8bb3a88
|
|
@ -3363,9 +3363,12 @@ unsigned PECastSize::test_width(Design*des, NetScope*scope, width_mode_t&)
|
||||||
ivl_assert(*this, size_);
|
ivl_assert(*this, size_);
|
||||||
ivl_assert(*this, base_);
|
ivl_assert(*this, base_);
|
||||||
|
|
||||||
|
expr_width_ = 0;
|
||||||
|
|
||||||
NetExpr*size_ex = elab_and_eval(des, scope, size_, -1, true);
|
NetExpr*size_ex = elab_and_eval(des, scope, size_, -1, true);
|
||||||
NetEConst*size_ce = dynamic_cast<NetEConst*>(size_ex);
|
NetEConst*size_ce = dynamic_cast<NetEConst*>(size_ex);
|
||||||
expr_width_ = size_ce ? size_ce->value().as_ulong() : 0;
|
if (size_ce && !size_ce->value().is_negative())
|
||||||
|
expr_width_ = size_ce->value().as_ulong();
|
||||||
delete size_ex;
|
delete size_ex;
|
||||||
if (expr_width_ == 0) {
|
if (expr_width_ == 0) {
|
||||||
cerr << get_fileline() << ": error: Cast size expression "
|
cerr << get_fileline() << ": error: Cast size expression "
|
||||||
|
|
|
||||||
|
|
@ -242,6 +242,13 @@ ivl_type_t struct_type_t::elaborate_type_raw(Design*des, NetScope*scope) const
|
||||||
; cur_name != curp->names->end() ; ++ cur_name) {
|
; cur_name != curp->names->end() ; ++ cur_name) {
|
||||||
decl_assignment_t*namep = *cur_name;
|
decl_assignment_t*namep = *cur_name;
|
||||||
|
|
||||||
|
if (packed_flag && namep->expr) {
|
||||||
|
cerr << namep->expr->get_fileline() << " error: "
|
||||||
|
<< "Packed structs must not have default member values."
|
||||||
|
<< endl;
|
||||||
|
des->errors++;
|
||||||
|
}
|
||||||
|
|
||||||
netstruct_t::member_t memb;
|
netstruct_t::member_t memb;
|
||||||
memb.name = namep->name;
|
memb.name = namep->name;
|
||||||
memb.net_type = elaborate_array_type(des, scope, *this,
|
memb.net_type = elaborate_array_type(des, scope, *this,
|
||||||
|
|
|
||||||
|
|
@ -1130,12 +1130,14 @@ void free_macros(void)
|
||||||
* variables. When the define is over, the def_finish() function
|
* variables. When the define is over, the def_finish() function
|
||||||
* executes the define and clears this text. The define_continue_flag
|
* executes the define and clears this text. The define_continue_flag
|
||||||
* is set if do_define detects that the definition is to be continued
|
* is set if do_define detects that the definition is to be continued
|
||||||
* on the next line.
|
* on the next line. The define_comment_flag is set when a multi-line comment is
|
||||||
|
* active in a define.
|
||||||
*/
|
*/
|
||||||
static char* define_text = 0;
|
static char* define_text = 0;
|
||||||
static size_t define_cnt = 0;
|
static size_t define_cnt = 0;
|
||||||
|
|
||||||
static int define_continue_flag = 0;
|
static int define_continue_flag = 0;
|
||||||
|
static int define_comment_flag = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The do_magic function puts the expansions of magic macros into
|
* The do_magic function puts the expansions of magic macros into
|
||||||
|
|
@ -1189,6 +1191,33 @@ static char *find_arg(char*ptr, char*head, char*arg)
|
||||||
return cp;
|
return cp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns 1 if the comment continues on the next line
|
||||||
|
*/
|
||||||
|
static int do_define_multiline_comment(char *replace_start,
|
||||||
|
const char *search_start)
|
||||||
|
{
|
||||||
|
char *tail = strstr(search_start, "*/");
|
||||||
|
|
||||||
|
if (!tail) {
|
||||||
|
if (search_start[strlen(search_start) - 1] == '\\') {
|
||||||
|
define_continue_flag = 1;
|
||||||
|
define_comment_flag = 1;
|
||||||
|
*replace_start++ = '\\';
|
||||||
|
} else {
|
||||||
|
define_comment_flag = 0;
|
||||||
|
fprintf(stderr, "%s:%u: Unterminated comment in define\n",
|
||||||
|
istack->path, istack->lineno+1);
|
||||||
|
}
|
||||||
|
*replace_start = '\0';
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
define_comment_flag = 0;
|
||||||
|
tail += 2;
|
||||||
|
memmove(replace_start, tail, strlen(tail) + 1);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Collect the definition. Normally, this returns 0. If there is a
|
* Collect the definition. Normally, this returns 0. If there is a
|
||||||
* continuation, then return 1 and this function may be called again
|
* continuation, then return 1 and this function may be called again
|
||||||
|
|
@ -1204,6 +1233,12 @@ static void do_define(void)
|
||||||
|
|
||||||
define_continue_flag = 0;
|
define_continue_flag = 0;
|
||||||
|
|
||||||
|
/* Are we in an multi-line comment? Look for the end */
|
||||||
|
if (define_comment_flag) {
|
||||||
|
if (do_define_multiline_comment(yytext, yytext))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* Look for comments in the definition, and remove them. */
|
/* Look for comments in the definition, and remove them. */
|
||||||
cp = strchr(yytext, '/');
|
cp = strchr(yytext, '/');
|
||||||
|
|
||||||
|
|
@ -1215,24 +1250,14 @@ static void do_define(void)
|
||||||
}
|
}
|
||||||
*cp = 0;
|
*cp = 0;
|
||||||
break;
|
break;
|
||||||
}
|
} else if (cp[1] == '*') {
|
||||||
|
if (do_define_multiline_comment(cp, cp + 2))
|
||||||
if (cp[1] == '*') {
|
|
||||||
tail = strstr(cp+2, "*/");
|
|
||||||
|
|
||||||
if (tail == 0) {
|
|
||||||
*cp = 0;
|
|
||||||
fprintf(stderr, "%s:%u: Unterminated comment in define\n",
|
|
||||||
istack->path, istack->lineno+1
|
|
||||||
);
|
|
||||||
break;
|
break;
|
||||||
|
} else {
|
||||||
|
cp++;
|
||||||
}
|
}
|
||||||
|
|
||||||
memmove(cp, tail+2, strlen(tail+2)+1);
|
cp = strchr(cp, '/');
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
cp = strchr(cp+1, '/');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Trim trailing white space. */
|
/* Trim trailing white space. */
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
// Check that variables referenced in a void function contribute to the
|
||||||
|
// sensitivity list of a always_comb block.
|
||||||
|
|
||||||
|
module top;
|
||||||
|
logic passed;
|
||||||
|
logic [7:0] value;
|
||||||
|
integer counter;
|
||||||
|
|
||||||
|
function automatic void count(bit what);
|
||||||
|
counter = 0;
|
||||||
|
for (integer i = 0; i < $bits(value); i++) begin
|
||||||
|
if (value[i] == what)
|
||||||
|
counter += 1;
|
||||||
|
end
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
always_comb begin
|
||||||
|
count(1'b1);
|
||||||
|
end
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
passed = 1'b1;
|
||||||
|
|
||||||
|
value = 8'b0000_0000;
|
||||||
|
#1;
|
||||||
|
if (counter !== 0) begin
|
||||||
|
$display("Expected 0, got %d", counter);
|
||||||
|
passed = 1'b0;
|
||||||
|
end
|
||||||
|
|
||||||
|
value = 8'b0011_1100;
|
||||||
|
#1;
|
||||||
|
if (counter !== 4) begin
|
||||||
|
$display("Expected 4, got %d", counter);
|
||||||
|
passed = 1'b0;
|
||||||
|
end
|
||||||
|
|
||||||
|
value = 8'b1011_1101;
|
||||||
|
#1;
|
||||||
|
if (counter !== 6) begin
|
||||||
|
$display("Expected 6, got %d", counter);
|
||||||
|
passed = 1'b0;
|
||||||
|
end
|
||||||
|
|
||||||
|
if (passed) begin
|
||||||
|
$display("PASSED");
|
||||||
|
end else begin
|
||||||
|
$display("FAILED");
|
||||||
|
end
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
// Check that a '*' or '/' following a C-style comment is supported in a macro
|
||||||
|
|
||||||
|
`define x(a, b) a /* comment */ * b
|
||||||
|
`define y(a, b) a /* comment */ / b
|
||||||
|
|
||||||
|
module test;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
if (`x(2, 3) === 6 && `y(8, 2) === 4) begin
|
||||||
|
$display("PASSED");
|
||||||
|
end else begin
|
||||||
|
$display("FAILED");
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
// Check that another comment directly following a C-style comment is
|
||||||
|
// supported in a macro.
|
||||||
|
|
||||||
|
`define x(a, b) a /* comment */// * b
|
||||||
|
`define y(a, b) a /* comment *//*/ b*/
|
||||||
|
|
||||||
|
module test;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
if (`x(2, 3) === 2 && `y(8, 2) === 8) begin
|
||||||
|
$display("PASSED");
|
||||||
|
end else begin
|
||||||
|
$display("FAILED");
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
// Check that a '/' directly after opening a C-style comment gets handled
|
||||||
|
// correctly in a macro.
|
||||||
|
|
||||||
|
`define x(a, b) a /*/ b */ + b
|
||||||
|
|
||||||
|
module test;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
if (`x(2, 3) === 5) begin
|
||||||
|
$display("PASSED");
|
||||||
|
end else begin
|
||||||
|
$display("FAILED");
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
// Check that multi-line comments in macros are supported. Including some corner
|
||||||
|
// cases like another comment start in the comment.
|
||||||
|
|
||||||
|
`define test(a, b, c) \
|
||||||
|
(a + /* these is some \
|
||||||
|
multi line */ b /* comment \
|
||||||
|
that goes on \
|
||||||
|
and on */ ) /* and some more \
|
||||||
|
\
|
||||||
|
// and even has a comments \
|
||||||
|
/* in the comment */ * c
|
||||||
|
|
||||||
|
module test;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
if (`test(1, 2, 3) === 9) begin
|
||||||
|
$display("PASSED");
|
||||||
|
end else begin
|
||||||
|
$display("FAILED");
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
// Check that an error is reported when using a zero value for a size cast.
|
||||||
|
|
||||||
|
module test;
|
||||||
|
|
||||||
|
localparam integer N = 0;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
int x, y;
|
||||||
|
y = N'(x); // This should fail, N is zero
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
// Check that an error is reported when using a negative value for a size cast.
|
||||||
|
|
||||||
|
module test;
|
||||||
|
|
||||||
|
localparam integer N = -1;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
int x, y;
|
||||||
|
y = N'(x); // This should fail, N is negative
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
// Check that an error is reported when using an undefined value for a size cast.
|
||||||
|
|
||||||
|
module test;
|
||||||
|
|
||||||
|
localparam integer N = 32'hx;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
int x, y;
|
||||||
|
y = N'(x); // This should fail, N is undefined
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
// Check that an error is reported when specifing a default member value for a
|
||||||
|
// packed struct.
|
||||||
|
|
||||||
|
module test;
|
||||||
|
struct packed {
|
||||||
|
// This should fail, default member value is not allowed for packed struct
|
||||||
|
integer x = 10;
|
||||||
|
} s;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
$display("FAILED");
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
|
|
@ -76,6 +76,7 @@ always_comb_fail4 CE,-g2005-sv ivltests
|
||||||
always_comb_no_sens nornal,-g2005-sv ivltests gold=always_comb_no_sens.gold
|
always_comb_no_sens nornal,-g2005-sv ivltests gold=always_comb_no_sens.gold
|
||||||
always_comb_rfunc nornal,-g2005-sv ivltests
|
always_comb_rfunc nornal,-g2005-sv ivltests
|
||||||
always_comb_trig normal,-g2005-sv ivltests
|
always_comb_trig normal,-g2005-sv ivltests
|
||||||
|
always_comb_void_func normal,-g2005-sv ivltests
|
||||||
always_comb_warn normal,-g2005-sv ivltests gold=always_comb_warn.gold
|
always_comb_warn normal,-g2005-sv ivltests gold=always_comb_warn.gold
|
||||||
always_ff normal,-g2005-sv ivltests
|
always_ff normal,-g2005-sv ivltests
|
||||||
always_ff_fail CE,-g2005-sv ivltests
|
always_ff_fail CE,-g2005-sv ivltests
|
||||||
|
|
@ -465,6 +466,9 @@ size_cast2 normal,-g2005-sv ivltests
|
||||||
size_cast3 normal,-g2009 ivltests
|
size_cast3 normal,-g2009 ivltests
|
||||||
size_cast4 normal,-g2009 ivltests
|
size_cast4 normal,-g2009 ivltests
|
||||||
size_cast5 normal,-g2009 ivltests
|
size_cast5 normal,-g2009 ivltests
|
||||||
|
size_cast_fail1 CE,-g2009 ivltests
|
||||||
|
size_cast_fail2 CE,-g2009 ivltests
|
||||||
|
size_cast_fail3 CE,-g2009 ivltests
|
||||||
slongint_test normal,-g2005-sv ivltests
|
slongint_test normal,-g2005-sv ivltests
|
||||||
sshortint_test normal,-g2005-sv ivltests
|
sshortint_test normal,-g2005-sv ivltests
|
||||||
string_events normal,-g2009 ivltests gold=string_events.gold
|
string_events normal,-g2009 ivltests gold=string_events.gold
|
||||||
|
|
@ -485,6 +489,7 @@ struct_member_signed normal,-g2009 ivltests
|
||||||
struct_packed_array normal,-g2009 ivltests
|
struct_packed_array normal,-g2009 ivltests
|
||||||
struct_packed_array2 normal,-g2009 ivltests
|
struct_packed_array2 normal,-g2009 ivltests
|
||||||
struct_packed_darray_fail CE,-g2009 ivltests
|
struct_packed_darray_fail CE,-g2009 ivltests
|
||||||
|
struct_packed_member_def CE,-g2009 ivltests
|
||||||
struct_packed_queue_fail CE,-g2009 ivltests
|
struct_packed_queue_fail CE,-g2009 ivltests
|
||||||
struct_packed_sysfunct normal,-g2009 ivltests
|
struct_packed_sysfunct normal,-g2009 ivltests
|
||||||
struct_packed_sysfunct2 normal,-g2009 ivltests
|
struct_packed_sysfunct2 normal,-g2009 ivltests
|
||||||
|
|
|
||||||
|
|
@ -635,6 +635,10 @@ localparam_type normal ivltests gold=parameter_type.gold
|
||||||
long_div normal ivltests gold=long_div.gold
|
long_div normal ivltests gold=long_div.gold
|
||||||
macro2 normal ivltests
|
macro2 normal ivltests
|
||||||
macro_args CO,-yivltests ivltests
|
macro_args CO,-yivltests ivltests
|
||||||
|
macro_comment1 normal ivltests
|
||||||
|
macro_comment2 normal ivltests
|
||||||
|
macro_comment3 normal ivltests
|
||||||
|
macro_comment_multiline normal ivltests
|
||||||
macro_redefinition normal,-Wmacro-redefinition ivltests gold=macro_redefinition.gold
|
macro_redefinition normal,-Wmacro-redefinition ivltests gold=macro_redefinition.gold
|
||||||
macro_replacement normal,-Wmacro-replacement ivltests gold=macro_replacement.gold
|
macro_replacement normal,-Wmacro-replacement ivltests gold=macro_replacement.gold
|
||||||
macsub normal ivltests
|
macsub normal ivltests
|
||||||
|
|
|
||||||
|
|
@ -69,6 +69,7 @@
|
||||||
|
|
||||||
# Verilog 95 does not support automatic tasks or functions.
|
# Verilog 95 does not support automatic tasks or functions.
|
||||||
always_comb_rfunc CE ivltests
|
always_comb_rfunc CE ivltests
|
||||||
|
always_comb_void_func CE ivltests
|
||||||
automatic_error11 CE ivltests
|
automatic_error11 CE ivltests
|
||||||
automatic_error12 CE ivltests
|
automatic_error12 CE ivltests
|
||||||
automatic_error13 CE ivltests
|
automatic_error13 CE ivltests
|
||||||
|
|
|
||||||
|
|
@ -255,6 +255,30 @@ NexusSet* NetETernary::nex_input(bool rem_out, bool always_sens, bool nested_fun
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get the contribution of a function call in a always_comb block
|
||||||
|
static void func_always_sens(NetFuncDef *func, NexusSet *result,
|
||||||
|
bool rem_out, bool nested_func)
|
||||||
|
{
|
||||||
|
// Avoid recursive function calls.
|
||||||
|
static set<NetFuncDef*> func_set;
|
||||||
|
if (!nested_func)
|
||||||
|
func_set.clear();
|
||||||
|
|
||||||
|
if (!func_set.insert(func).second)
|
||||||
|
return;
|
||||||
|
|
||||||
|
std::unique_ptr<NexusSet> tmp(func->proc()->nex_input(rem_out, true, true));
|
||||||
|
// Remove the function inputs
|
||||||
|
std::unique_ptr<NexusSet> in(new NexusSet);
|
||||||
|
for (unsigned idx = 0; idx < func->port_count(); idx++) {
|
||||||
|
NetNet *net = func->port(idx);
|
||||||
|
assert(net->pin_count() == 1);
|
||||||
|
in->add(net->pin(0).nexus(), 0, net->vector_width());
|
||||||
|
}
|
||||||
|
tmp->rem(*in);
|
||||||
|
result->add(*tmp);
|
||||||
|
}
|
||||||
|
|
||||||
NexusSet* NetEUFunc::nex_input(bool rem_out, bool always_sens, bool nested_func) const
|
NexusSet* NetEUFunc::nex_input(bool rem_out, bool always_sens, bool nested_func) const
|
||||||
{
|
{
|
||||||
NexusSet*result = new NexusSet;
|
NexusSet*result = new NexusSet;
|
||||||
|
|
@ -265,31 +289,8 @@ NexusSet* NetEUFunc::nex_input(bool rem_out, bool always_sens, bool nested_func)
|
||||||
delete tmp;
|
delete tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (always_sens) {
|
if (always_sens)
|
||||||
NetFuncDef*func = func_->func_def();
|
func_always_sens(func_->func_def(), result, rem_out, nested_func);
|
||||||
|
|
||||||
// Avoid recursive function calls.
|
|
||||||
static set<NetFuncDef*> func_set;
|
|
||||||
if (!nested_func)
|
|
||||||
func_set.clear();
|
|
||||||
|
|
||||||
if (!func_set.insert(func).second)
|
|
||||||
return result;
|
|
||||||
|
|
||||||
NexusSet*tmp = func->proc()->nex_input(rem_out, always_sens, true);
|
|
||||||
// Remove the function inputs
|
|
||||||
NexusSet*in = new NexusSet;
|
|
||||||
for (unsigned idx = 0 ; idx < func->port_count() ; idx += 1) {
|
|
||||||
NetNet*net = func->port(idx);
|
|
||||||
assert(net->pin_count() == 1);
|
|
||||||
in->add(net->pin(0).nexus(), 0, net->vector_width());
|
|
||||||
}
|
|
||||||
tmp->rem(*in);
|
|
||||||
delete in;
|
|
||||||
|
|
||||||
result->add(*tmp);
|
|
||||||
delete tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
@ -613,9 +614,18 @@ NexusSet* NetSTask::nex_input(bool rem_out, bool always_sens, bool nested_func)
|
||||||
* parameters to consider, because the compiler already removed them
|
* parameters to consider, because the compiler already removed them
|
||||||
* and converted them to blocking assignments.
|
* and converted them to blocking assignments.
|
||||||
*/
|
*/
|
||||||
NexusSet* NetUTask::nex_input(bool, bool, bool) const
|
NexusSet* NetUTask::nex_input(bool rem_out, bool always_sens, bool nested_func) const
|
||||||
{
|
{
|
||||||
return new NexusSet;
|
NexusSet *result = new NexusSet;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Let the contents of void functions contribute to the sensitivity list
|
||||||
|
* of always_comb blocks
|
||||||
|
*/
|
||||||
|
if (always_sens && task_->type() == NetScope::FUNC)
|
||||||
|
func_always_sens(task_->func_def(), result, rem_out, nested_func);
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
NexusSet* NetWhile::nex_input(bool rem_out, bool always_sens, bool nested_func) const
|
NexusSet* NetWhile::nex_input(bool rem_out, bool always_sens, bool nested_func) const
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue