Skip to content

Commit f449089

Browse files
authored
Merge pull request #239 from CheeksTheGeek/chore/warn-for-wait-and-expect
Warn & Ignore for wait, expect and program
2 parents cc4ec6e + d6c3224 commit f449089

File tree

10 files changed

+127
-25
lines changed

10 files changed

+127
-25
lines changed

src/diag.cc

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ namespace diag {
5555
DiagCode EdgeImplicitMixing(DiagSubsystem::Netlist, 1002);
5656
DiagCode GenericTimingUnsyn(DiagSubsystem::Netlist, 1003);
5757
DiagCode BothEdgesUnsupported(DiagSubsystem::Netlist, 1004);
58+
DiagCode WaitStatementUnsupported(DiagSubsystem::Netlist, 1011);
5859
DiagCode NoteSignalEvent(DiagSubsystem::Netlist, 1005);
5960
DiagCode ExpectingIfElseAload(DiagSubsystem::Netlist, 1006);
6061
DiagCode NoteDuplicateEdgeSense(DiagSubsystem::Netlist, 1007);
@@ -95,19 +96,21 @@ namespace diag {
9596
DiagCode PortCorrespondence(DiagSubsystem::Netlist, 1042);
9697
DiagCode UnsynthesizableFeature(DiagSubsystem::Netlist, 1043);
9798
DiagCode SVAUnsupported(DiagSubsystem::Netlist, 1044);
98-
DiagCode ForbiddenDemotion(DiagSubsystem::Netlist, 1045);
99-
DiagCode UdpUnsupported(DiagSubsystem::Netlist, 1046);
100-
DiagCode PrimTypeUnsupported(DiagSubsystem::Netlist, 1047);
101-
DiagCode ReferenceAcrossKeptHierBoundary(DiagSubsystem::Netlist, 1048);
102-
DiagCode NoteModuleBlackboxBecauseAttribute(DiagSubsystem::Netlist, 1049);
103-
DiagCode NoteModuleBlackboxBecauseEmpty(DiagSubsystem::Netlist, 1050);
104-
DiagCode NoteModuleNotDissolvedBecauseBlackbox(DiagSubsystem::Netlist, 1051);
105-
DiagCode NoteModuleNotDissolvedBecauseKeepHierarchy(DiagSubsystem::Netlist, 1052);
106-
DiagCode BlockingAssignmentAfterNonblocking(DiagSubsystem::Netlist, 1053);
107-
DiagCode NonblockingAssignmentAfterBlocking(DiagSubsystem::Netlist, 1054);
108-
DiagCode NotePreviousAssignment(DiagSubsystem::Netlist, 1055);
109-
DiagCode NetTypeUnsupported(DiagSubsystem::Netlist, 1056);
110-
DiagCode NoAllowTopLevelIfacePorts(DiagSubsystem::Netlist, 1057);
99+
DiagCode ExpectStatementUnsupported(DiagSubsystem::Netlist, 1045);
100+
DiagCode ProgramUnsupported(DiagSubsystem::Netlist, 1046);
101+
DiagCode ForbiddenDemotion(DiagSubsystem::Netlist, 1047);
102+
DiagCode UdpUnsupported(DiagSubsystem::Netlist, 1048);
103+
DiagCode PrimTypeUnsupported(DiagSubsystem::Netlist, 1049);
104+
DiagCode ReferenceAcrossKeptHierBoundary(DiagSubsystem::Netlist, 1050);
105+
DiagCode NoteModuleBlackboxBecauseAttribute(DiagSubsystem::Netlist, 1051);
106+
DiagCode NoteModuleBlackboxBecauseEmpty(DiagSubsystem::Netlist, 1052);
107+
DiagCode NoteModuleNotDissolvedBecauseBlackbox(DiagSubsystem::Netlist, 1053);
108+
DiagCode NoteModuleNotDissolvedBecauseKeepHierarchy(DiagSubsystem::Netlist, 1054);
109+
DiagCode BlockingAssignmentAfterNonblocking(DiagSubsystem::Netlist, 1055);
110+
DiagCode NonblockingAssignmentAfterBlocking(DiagSubsystem::Netlist, 1056);
111+
DiagCode NotePreviousAssignment(DiagSubsystem::Netlist, 1057);
112+
DiagCode NetTypeUnsupported(DiagSubsystem::Netlist, 1058);
113+
DiagCode NoAllowTopLevelIfacePorts(DiagSubsystem::Netlist, 1059);
111114

112115
DiagGroup unsynthesizable("unsynthesizable", {IffUnsupported, GenericTimingUnsyn, BothEdgesUnsupported, ExpectingIfElseAload,
113116
IfElseAloadPolarity, IfElseAloadMismatch, UnsynthesizableFeature});
@@ -121,6 +124,8 @@ namespace diag {
121124
engine.setMessage(EdgeImplicitMixing, "mixing of implicit and edge sensitivity");
122125
engine.setMessage(GenericTimingUnsyn, "unsynthesizable timing control (ignore with '--ignore-timing')");
123126
engine.setMessage(BothEdgesUnsupported, "'edge' sensitivity will not be synthesized");
127+
engine.setMessage(WaitStatementUnsupported, "wait statement will not be synthesized");
128+
engine.setSeverity(WaitStatementUnsupported, DiagnosticSeverity::Warning);
124129
engine.setMessage(NoteSignalEvent, "signal event specified here");
125130
engine.setSeverity(NoteSignalEvent, DiagnosticSeverity::Note);
126131

@@ -223,6 +228,12 @@ namespace diag {
223228
engine.setMessage(SVAUnsupported, "SVA unsupported (ignore all assertions with '--ignore-assertions')");
224229
engine.setSeverity(SVAUnsupported, DiagnosticSeverity::Error);
225230

231+
engine.setMessage(ExpectStatementUnsupported, "expect statement will not be synthesized");
232+
engine.setSeverity(ExpectStatementUnsupported, DiagnosticSeverity::Warning);
233+
234+
engine.setMessage(ProgramUnsupported, "program block will not be synthesized");
235+
engine.setSeverity(ProgramUnsupported, DiagnosticSeverity::Warning);
236+
226237
engine.setMessage(ForbiddenDemotion, "disabling error '{}' is unsupported with yosys-slang");
227238
engine.setSeverity(ForbiddenDemotion, DiagnosticSeverity::Error);
228239

src/diag.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ extern slang::DiagCode SignalSensitivityAmbiguous;
1515
extern slang::DiagCode EdgeImplicitMixing;
1616
extern slang::DiagCode GenericTimingUnsyn;
1717
extern slang::DiagCode BothEdgesUnsupported;
18+
extern slang::DiagCode WaitStatementUnsupported;
1819
extern slang::DiagCode NoteSignalEvent;
1920
extern slang::DiagCode ExpectingIfElseAload;
2021
extern slang::DiagCode NoteDuplicateEdgeSense;
@@ -51,6 +52,8 @@ extern slang::DiagCode NoteIgnoreInitial;
5152
extern slang::DiagCode PortCorrespondence;
5253
extern slang::DiagCode UnsynthesizableFeature;
5354
extern slang::DiagCode SVAUnsupported;
55+
extern slang::DiagCode ExpectStatementUnsupported;
56+
extern slang::DiagCode ProgramUnsupported;
5457
extern slang::DiagCode ForbiddenDemotion;
5558
extern slang::DiagCode UdpUnsupported;
5659
extern slang::DiagCode PrimTypeUnsupported;

src/initial_eval.cc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -706,6 +706,12 @@ ER EvalVisitor::visit(const TimedStatement &stmt)
706706
return result;
707707
}
708708

709+
ER EvalVisitor::visit(const slang::ast::WaitStatement &stmt)
710+
{
711+
context.addDiag(slang_frontend::diag::WaitStatementUnsupported, stmt.sourceRange);
712+
return ER::Success;
713+
}
714+
709715
ER EvalVisitor::visit(const EmptyStatement&)
710716
{
711717
return ER::Success;

src/initial_eval.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ struct EvalVisitor {
3434
ER visit(const slang::ast::ExpressionStatement &stmt);
3535
ER visit(const slang::ast::ImmediateAssertionStatement &stmt);
3636
ER visit(const slang::ast::TimedStatement &stmt);
37+
ER visit(const slang::ast::WaitStatement &stmt);
3738
ER visit(const slang::ast::EmptyStatement &stmt);
3839
ER visit(const slang::ast::Statement &);
3940

src/slang_frontend.cc

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -671,7 +671,11 @@ struct StatementVisitor : public ast::ASTVisitor<StatementVisitor, true, false>
671671

672672
void handle(const ast::ConcurrentAssertionStatement &stmt) {
673673
if (!netlist.settings.ignore_assertions.value_or(false)) {
674-
netlist.add_diag(diag::SVAUnsupported, stmt.sourceRange);
674+
if (stmt.assertionKind == ast::AssertionKind::Expect) {
675+
netlist.add_diag(diag::ExpectStatementUnsupported, stmt.sourceRange);
676+
} else {
677+
netlist.add_diag(diag::SVAUnsupported, stmt.sourceRange);
678+
}
675679
}
676680
}
677681

@@ -1109,6 +1113,11 @@ struct StatementVisitor : public ast::ASTVisitor<StatementVisitor, true, false>
11091113
stmt.stmt.visit(*this);
11101114
}
11111115

1116+
void handle(const ast::WaitStatement &stmt)
1117+
{
1118+
netlist.add_diag(diag::WaitStatementUnsupported, stmt.sourceRange);
1119+
}
1120+
11121121
void handle(const ast::Statement &stmt)
11131122
{
11141123
netlist.add_diag(diag::LangFeatureUnsupported, stmt.sourceRange.start());
@@ -2079,13 +2088,13 @@ struct PopulateNetlist : public TimingPatternInterpretor, public ast::ASTVisitor
20792088

20802089
RTLIL::Cell *cell;
20812090
if (aloads.empty()) {
2082-
for (auto [named_chunk, name] : generate_subfield_names(driven_chunk, type)) {
2083-
cell = netlist.canvas->addDff(netlist.canvas->uniquify("$driver$" + RTLIL::unescape_id(netlist.id(*named_chunk.variable.get_symbol())) + name),
2084-
timing.triggers[0].signal,
2085-
assigned.extract(named_chunk.base - driven_chunk.base, named_chunk.bitwidth()),
2086-
netlist.convert_static(named_chunk),
2087-
timing.triggers[0].edge_polarity);
2088-
transfer_attrs(symbol, cell);
2091+
for (auto [named_chunk, name] : generate_subfield_names(driven_chunk, type)) {
2092+
cell = netlist.canvas->addDff(netlist.canvas->uniquify("$driver$" + RTLIL::unescape_id(netlist.id(*named_chunk.variable.get_symbol())) + name),
2093+
timing.triggers[0].signal,
2094+
assigned.extract(named_chunk.base - driven_chunk.base, named_chunk.bitwidth()),
2095+
netlist.convert_static(named_chunk),
2096+
timing.triggers[0].edge_polarity);
2097+
transfer_attrs(symbol, cell);
20892098
}
20902099
} else if (aloads.size() == 1) {
20912100
VariableBits aldff_q;
@@ -2227,6 +2236,11 @@ struct PopulateNetlist : public TimingPatternInterpretor, public ast::ASTVisitor
22272236

22282237
void handle(const ast::InstanceSymbol &sym)
22292238
{
2239+
if (sym.getDefinition().definitionKind == ast::DefinitionKind::Program) {
2240+
netlist.add_diag(diag::ProgramUnsupported, sym.location);
2241+
return;
2242+
}
2243+
22302244
// blackboxes get special handling no matter the hierarchy mode
22312245
if (sym.isModule() && netlist.is_blackbox(sym.body.getDefinition())) {
22322246
RTLIL::Cell *cell = netlist.canvas->addCell(netlist.id(sym), RTLIL::escape_id(std::string(sym.body.name)));
@@ -3538,6 +3552,12 @@ struct SlangFrontend : Frontend {
35383552

35393553
HierarchyQueue hqueue;
35403554
for (auto instance : compilation->getRoot().topInstances) {
3555+
if (instance->getDefinition().definitionKind == ast::DefinitionKind::Program) {
3556+
slang::Diagnostic program_diag(diag::ProgramUnsupported, instance->location);
3557+
driver.diagEngine.issue(program_diag);
3558+
continue;
3559+
}
3560+
35413561
auto ref_body = &get_instance_body(settings, *instance);
35423562
log_assert(ref_body->parentInstance);
35433563
auto [netlist, new_] = hqueue.get_or_emplace(ref_body, design, settings,

tests/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@ set(ALL_TESTS
5454
various/top_attr.ys
5555
various/unknown_cells.ys
5656
various/toplevel_intf_unsupported.ys
57+
various/wait_test.ys
58+
various/expect_test.ys
59+
various/program_test.ys
5760
)
5861

5962
foreach(test_script ${ALL_TESTS})

tests/run.sh

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,25 @@ YOSYS=yosys
33
TESTSDIR="$(dirname "${BASH_SOURCE[0]}")"
44
PLUGIN="$(realpath "$TESTSDIR/../build/slang.so")"
55
code=0
6+
NOCOLOR='\033[0m'
7+
RED='\033[0;31m'
8+
GREEN='\033[0;32m'
9+
BOLD='\033[1m'
10+
611
for testcase in "$TESTSDIR"/*/*.ys "$TESTSDIR"/*/*.tcl;
712
do
813
TEXT=$testcase;
914
base=$(basename "$testcase")
1015
dir=$(dirname "$testcase")
1116
echo -n "${TEXT}... ";
12-
if ! (cd "$dir" && exec "$YOSYS" -m "$PLUGIN" "$base" 1>/dev/null 2>&1); then
13-
echo -e "\e[31mFAIL\e[0m";
14-
echo -e "Testcase \e[1m${testcase}\e[0m failed";
17+
if ! (cd "$dir" && exec "$YOSYS" -m "$PLUGIN" "$base" >/dev/null 2>&1); then
18+
echo -e "${RED}FAIL${NOCOLOR}";
19+
echo -e "Testcase ${BOLD}${testcase}${NOCOLOR} failed";
1520
(cd "$dir" && exec "$YOSYS" -g -Q -m "$PLUGIN" "$base");
1621
echo;
1722
code=1;
1823
else
19-
echo -e "\e[32mOK\e[0m";
24+
echo -e "${GREEN}OK${NOCOLOR}";
2025
fi
2126
done;
2227
exit $code

tests/various/expect_test.ys

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
read_slang <<EOF
2+
module expect_test(input logic clk, input logic a, input logic b, input logic c, output logic q);
3+
logic i;
4+
always_ff @(posedge clk) begin
5+
expect (@(posedge clk) a ##1 b ##1 c) else $error("expect failed");
6+
expect (##[1:10] a && b) q = 1'b1;
7+
q <= a & b;
8+
end
9+
endmodule
10+
EOF
11+
12+
test_slangdiag -expect "expect statement will not be synthesized"

tests/various/program_test.ys

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
read_slang <<EOF
2+
module regular_module(input logic clk, output logic q);
3+
always_ff @(posedge clk) begin
4+
q <= 1'b1;
5+
end
6+
endmodule
7+
8+
program tst;
9+
logic clk, q;
10+
11+
initial begin
12+
clk = 0;
13+
forever #5 clk = ~clk;
14+
end
15+
16+
initial begin
17+
#100;
18+
$display("Test completed");
19+
$finish;
20+
end
21+
endprogram
22+
EOF
23+
24+
test_slangdiag -expect "program block will not be synthesized"

tests/various/wait_test.ys

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
read_slang <<EOF
2+
module wait_test(input logic clk, input logic rst, output logic q);
3+
logic condition = 1'b0;
4+
initial begin
5+
wait(condition);
6+
q = 1'b1;
7+
end
8+
always_ff @(posedge clk)
9+
if (rst) condition <= 1'b0;
10+
else begin
11+
wait(condition == 1'b1);
12+
q <= 1'b1;
13+
end
14+
endmodule
15+
EOF
16+
17+
test_slangdiag -expect "wait statement will not be synthesized"

0 commit comments

Comments
 (0)