Merge aaa1945549 into c7530dbcc1
This commit is contained in:
commit
89b8f0e2a9
89
elaborate.cc
89
elaborate.cc
|
|
@ -35,6 +35,8 @@
|
|||
# include <iostream>
|
||||
# include <sstream>
|
||||
# include <list>
|
||||
# include <map>
|
||||
# include <set>
|
||||
# include "pform.h"
|
||||
# include "PClass.h"
|
||||
# include "PEvent.h"
|
||||
|
|
@ -7662,6 +7664,89 @@ static void check_ff_sensitivity(const NetProc* statement)
|
|||
}
|
||||
}
|
||||
|
||||
bool Design::check_always_ff_lvals()
|
||||
{
|
||||
bool result = false;
|
||||
map<const Nexus*, const NetProcTop*> always_ff_lvals;
|
||||
|
||||
for (NetProcTop*pr = procs_ ; pr ; pr = pr->next_) {
|
||||
if (pr->type() != IVL_PR_ALWAYS_FF)
|
||||
continue;
|
||||
|
||||
NexusSet outputs;
|
||||
pr->statement()->nex_output(outputs);
|
||||
|
||||
set<const Nexus*> seen_outputs;
|
||||
for (unsigned idx = 0 ; idx < outputs.size() ; idx += 1) {
|
||||
const NexusSet::elem_t&output = outputs[idx];
|
||||
const Nexus*nexus = output.lnk.nexus();
|
||||
if (! seen_outputs.insert(nexus).second)
|
||||
continue;
|
||||
|
||||
auto cur = always_ff_lvals.find(nexus);
|
||||
if (cur == always_ff_lvals.end()) {
|
||||
always_ff_lvals[nexus] = pr;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cur->second == pr)
|
||||
continue;
|
||||
|
||||
const char*name = nexus->name();
|
||||
cerr << cur->second->get_fileline() << ": error: "
|
||||
"variable '" << name << "' written in an "
|
||||
"always_ff process may not be written by any "
|
||||
"other process." << endl;
|
||||
cerr << pr->get_fileline() << ": : "
|
||||
"process also writes variable '" << name
|
||||
<< "'." << endl;
|
||||
result = true;
|
||||
errors += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (always_ff_lvals.empty())
|
||||
return result;
|
||||
|
||||
for (NetProcTop*pr = procs_ ; pr ; pr = pr->next_) {
|
||||
if (pr->type() == IVL_PR_ALWAYS_FF)
|
||||
continue;
|
||||
|
||||
if ((pr->type() == IVL_PR_INITIAL) &&
|
||||
(pr->attribute(perm_string::literal("_ivl_schedule_init"))
|
||||
.as_ulong() != 0))
|
||||
continue;
|
||||
|
||||
NexusSet outputs;
|
||||
pr->statement()->nex_output(outputs);
|
||||
|
||||
set<const Nexus*> seen_outputs;
|
||||
for (unsigned idx = 0 ; idx < outputs.size() ; idx += 1) {
|
||||
const NexusSet::elem_t&output = outputs[idx];
|
||||
const Nexus*nexus = output.lnk.nexus();
|
||||
if (! seen_outputs.insert(nexus).second)
|
||||
continue;
|
||||
|
||||
auto cur = always_ff_lvals.find(nexus);
|
||||
if (cur == always_ff_lvals.end())
|
||||
continue;
|
||||
|
||||
const char*name = nexus->name();
|
||||
cerr << cur->second->get_fileline() << ": error: "
|
||||
"variable '" << name << "' written in an "
|
||||
"always_ff process may not be written by any "
|
||||
"other process." << endl;
|
||||
cerr << pr->get_fileline() << ": : "
|
||||
"process also writes variable '" << name
|
||||
<< "'." << endl;
|
||||
result = true;
|
||||
errors += 1;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check to see if the always_* processes only contain synthesizable
|
||||
* constructs.
|
||||
|
|
@ -8088,6 +8173,10 @@ Design* elaborate(list<perm_string>roots)
|
|||
// synthesizable constructs
|
||||
has_failure |= des->check_proc_synth();
|
||||
|
||||
// Check that always_ff l-values are not also written by another
|
||||
// process.
|
||||
has_failure |= des->check_always_ff_lvals();
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << "<toplevel>" << ": debug: "
|
||||
<< " finishing with "
|
||||
|
|
|
|||
|
|
@ -0,0 +1,7 @@
|
|||
ivltests/always_ff_lval_fail.v:33: error: variable 'ff_ff_driver.q' written in an always_ff process may not be written by any other process.
|
||||
ivltests/always_ff_lval_fail.v:29: : process also writes variable 'ff_ff_driver.q'.
|
||||
ivltests/always_ff_lval_fail.v:6: error: variable 'ff_initial_driver.a' written in an always_ff process may not be written by any other process.
|
||||
ivltests/always_ff_lval_fail.v:4: : process also writes variable 'ff_initial_driver.a'.
|
||||
ivltests/always_ff_lval_fail.v:19: error: variable 'ff_always_driver.q' written in an always_ff process may not be written by any other process.
|
||||
ivltests/always_ff_lval_fail.v:15: : process also writes variable 'ff_always_driver.q'.
|
||||
Elaboration failed
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
module ff_initial_driver;
|
||||
logic a;
|
||||
|
||||
initial a = 1'b0;
|
||||
|
||||
always_ff @(posedge a) begin
|
||||
a <= 1'b1;
|
||||
end
|
||||
endmodule
|
||||
|
||||
module ff_always_driver;
|
||||
logic clk;
|
||||
logic q;
|
||||
|
||||
always @* begin
|
||||
q = clk;
|
||||
end
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
q <= 1'b1;
|
||||
end
|
||||
endmodule
|
||||
|
||||
module ff_ff_driver;
|
||||
logic clk1;
|
||||
logic clk2;
|
||||
logic q;
|
||||
|
||||
always_ff @(posedge clk1) begin
|
||||
q <= 1'b0;
|
||||
end
|
||||
|
||||
always_ff @(posedge clk2) begin
|
||||
q <= 1'b1;
|
||||
end
|
||||
endmodule
|
||||
|
|
@ -1,19 +1,24 @@
|
|||
module top;
|
||||
logic [9:0] pipe = 0;
|
||||
logic [9:0] pipe;
|
||||
logic [4:0] i;
|
||||
logic clk = 0;
|
||||
logic rst = 1;
|
||||
|
||||
always #1 clk = ~clk;
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
for (i=0; i<9; i++) begin
|
||||
pipe[i+1] <= pipe[i];
|
||||
if (rst) begin
|
||||
pipe <= 10'b0000000001;
|
||||
end else begin
|
||||
for (i=0; i<9; i++) begin
|
||||
pipe[i+1] <= pipe[i];
|
||||
end
|
||||
pipe[0] <= pipe[9];
|
||||
end
|
||||
pipe[0] <= pipe[9];
|
||||
end
|
||||
|
||||
initial begin
|
||||
pipe[0] = 1'b1;
|
||||
#2 rst = 0;
|
||||
|
||||
for (int j=0; j<10; j++) begin
|
||||
$display(pipe[9]);
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
# Test list files are a list of test names and the json that
|
||||
# describes the test.
|
||||
|
||||
always_ff_lval_fail vvp_tests/always_ff_lval_fail.json
|
||||
always4A vvp_tests/always4A.json
|
||||
always4B vvp_tests/always4B.json
|
||||
analog1 vvp_tests/analog1.json
|
||||
|
|
|
|||
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"type" : "CE",
|
||||
"source" : "always_ff_lval_fail.v",
|
||||
"iverilog-args" : [ "-g2005-sv" ],
|
||||
"gold" : "always_ff_lval_fail"
|
||||
}
|
||||
Loading…
Reference in New Issue