Skip to content

Commit 37806d5

Browse files
authored
Merge branch 'YosysHQ:main' into main
2 parents 082adf8 + af0b263 commit 37806d5

File tree

8 files changed

+172
-16
lines changed

8 files changed

+172
-16
lines changed

Makefile

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ ifeq ($(OS), Haiku)
176176
CXXFLAGS += -D_DEFAULT_SOURCE
177177
endif
178178

179-
YOSYS_VER := 0.55+23
179+
YOSYS_VER := 0.55+36
180180
YOSYS_MAJOR := $(shell echo $(YOSYS_VER) | cut -d'.' -f1)
181181
YOSYS_MINOR := $(shell echo $(YOSYS_VER) | cut -d'.' -f2)
182182
YOSYS_COMMIT := $(shell echo $(YOSYS_VER) | cut -d'.' -f3)
@@ -1039,6 +1039,12 @@ unit-test: libyosys.so
10391039
clean-unit-test:
10401040
@$(MAKE) -C $(UNITESTPATH) clean
10411041

1042+
install-dev: $(PROGRAM_PREFIX)yosys-config share
1043+
$(INSTALL_SUDO) mkdir -p $(DESTDIR)$(BINDIR)
1044+
$(INSTALL_SUDO) cp $(PROGRAM_PREFIX)yosys-config $(DESTDIR)$(BINDIR)
1045+
$(INSTALL_SUDO) mkdir -p $(DESTDIR)$(DATDIR)
1046+
$(INSTALL_SUDO) cp -r share/. $(DESTDIR)$(DATDIR)/.
1047+
10421048
install: $(TARGETS) $(EXTRA_TARGETS)
10431049
$(INSTALL_SUDO) mkdir -p $(DESTDIR)$(BINDIR)
10441050
$(INSTALL_SUDO) cp $(filter-out libyosys.so,$(TARGETS)) $(DESTDIR)$(BINDIR)
@@ -1281,5 +1287,5 @@ echo-cxx:
12811287

12821288
FORCE:
12831289

1284-
.PHONY: all top-all abc test install install-abc docs clean mrproper qtcreator coverage vcxsrc
1290+
.PHONY: all top-all abc test install-dev install install-abc docs clean mrproper qtcreator coverage vcxsrc
12851291
.PHONY: config-clean config-clang config-gcc config-gcc-static config-gprof config-sudo

backends/firrtl/firrtl.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1223,6 +1223,7 @@ struct FirrtlBackend : public Backend {
12231223
Pass::call(design, "demuxmap");
12241224
Pass::call(design, "bwmuxmap");
12251225

1226+
used_names.clear();
12261227
namecache.clear();
12271228
autoid_counter = 0;
12281229

@@ -1262,6 +1263,7 @@ struct FirrtlBackend : public Backend {
12621263
}
12631264
}
12641265

1266+
used_names.clear();
12651267
namecache.clear();
12661268
autoid_counter = 0;
12671269
}

passes/techmap/dfflibmap.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ static bool parse_next_state(const LibertyAst *cell, const LibertyAst *attr, std
9292
auto expr = attr->value;
9393
auto cell_name = cell->args[0];
9494

95-
for (size_t pos = expr.find_first_of("\" \t"); pos != std::string::npos; pos = expr.find_first_of("\" \t"))
95+
for (size_t pos = expr.find_first_of("\"\t"); pos != std::string::npos; pos = expr.find_first_of("\"\t"))
9696
expr.erase(pos, 1);
9797

9898
// if this isn't an enable flop, the next_state variable is usually just the input pin name.
@@ -117,6 +117,7 @@ static bool parse_next_state(const LibertyAst *cell, const LibertyAst *attr, std
117117
// the next_state variable isn't just a pin name; perhaps this is an enable?
118118
auto helper = LibertyExpression::Lexer(expr);
119119
auto tree = LibertyExpression::parse(helper);
120+
// log_debug("liberty expression:\n%s\n", tree.str().c_str());
120121

121122
if (tree.kind == LibertyExpression::Kind::EMPTY) {
122123
if (!warned_cells.count(cell_name)) {

passes/techmap/libparse.cc

Lines changed: 67 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,12 @@ void LibertyAst::dump(FILE *f, sieve &blacklist, sieve &whitelist, std::string i
163163
}
164164

165165
#ifndef FILTERLIB
166+
167+
// binary operators excluding ' '
168+
bool LibertyExpression::is_nice_binop(char c) {
169+
return c == '*' || c == '&' || c == '^' || c == '+' || c == '|';
170+
}
171+
166172
// https://matklad.github.io/2020/04/13/simple-but-powerful-pratt-parsing.html
167173
LibertyExpression LibertyExpression::parse(Lexer &s, int min_prio) {
168174
if (s.empty())
@@ -201,15 +207,8 @@ LibertyExpression LibertyExpression::parse(Lexer &s, int min_prio) {
201207
while (true) {
202208
if (s.empty())
203209
break;
204-
205-
c = s.peek();
206210

207-
while (isspace(c)) {
208-
if (s.empty())
209-
return lhs;
210-
s.next();
211-
c = s.peek();
212-
}
211+
c = s.peek();
213212

214213
if (c == '\'') { // postfix NOT
215214
if (min_prio > 7)
@@ -235,13 +234,31 @@ LibertyExpression LibertyExpression::parse(Lexer &s, int min_prio) {
235234
lhs = std::move(n);
236235

237236
continue;
238-
} else if (c == '&' || c == '*') { // infix AND
239-
// technically space should be considered infix AND. it seems rare in practice.
237+
} else if (c == '&' || c == '*' || isspace(c)) { // infix AND
240238
if (min_prio > 3)
241239
break;
242-
s.next();
240+
241+
if (isspace(c)) {
242+
// Rewind past this space and any further spaces
243+
while (isspace(c)) {
244+
if (s.empty())
245+
return lhs;
246+
s.next();
247+
c = s.peek();
248+
}
249+
if (is_nice_binop(c)) {
250+
// We found a real binop, so this space wasn't an AND
251+
// and we just discard it as meaningless whitespace
252+
continue;
253+
}
254+
} else {
255+
// Rewind past this op
256+
s.next();
257+
}
243258

244259
auto rhs = parse(s, 4);
260+
if (rhs.kind == EMPTY)
261+
continue;
245262
auto n = LibertyExpression{};
246263
n.kind = Kind::AND;
247264
n.children.push_back(lhs);
@@ -306,6 +323,45 @@ bool LibertyExpression::eval(dict<std::string, bool>& values) {
306323
}
307324
return false;
308325
}
326+
327+
std::string LibertyExpression::str(int indent)
328+
{
329+
std::string prefix;
330+
switch (kind) {
331+
case AND:
332+
prefix += "(and ";
333+
break;
334+
case OR:
335+
prefix += "(or ";
336+
break;
337+
case NOT:
338+
prefix += "(not ";
339+
break;
340+
case XOR:
341+
prefix += "(xor ";
342+
break;
343+
case PIN:
344+
prefix += "(pin \"" + name + "\"";
345+
break;
346+
case EMPTY:
347+
prefix += "(";
348+
break;
349+
default:
350+
log_assert(false);
351+
}
352+
size_t add_indent = prefix.length();
353+
bool first = true;
354+
for (auto child : children) {
355+
if (!first) {
356+
prefix += "\n" + std::string(indent + add_indent, ' ');
357+
}
358+
prefix += child.str(indent + add_indent);
359+
first = false;
360+
}
361+
prefix += ")";
362+
return prefix;
363+
}
364+
309365
#endif
310366

311367
int LibertyParser::lexer(std::string &str)

passes/techmap/libparse.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,9 @@ namespace Yosys
9393
static LibertyExpression parse(Lexer &s, int min_prio = 0);
9494
void get_pin_names(pool<std::string>& names);
9595
bool eval(dict<std::string, bool>& values);
96+
std::string str(int indent = 0);
97+
private:
98+
static bool is_nice_binop(char c);
9699
};
97100

98101
class LibertyInputStream {

tests/techmap/dfflibmap.lib

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ library(test) {
5555
cell (dffe) {
5656
area : 6;
5757
ff("IQ", "IQN") {
58-
next_state : "(D&EN) | (IQ&!EN)";
58+
next_state : "(D EN) | (IQ !EN)";
5959
clocked_on : "!CLK";
6060
}
6161
pin(D) {

tests/unit/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ $(OBJTEST)/%.o: $(basename $(subst $(OBJTEST),.,%)).cc
2424
.PHONY: prepare run-tests clean
2525

2626
run-tests: $(TESTS)
27-
$(subst Test ,Test; ,$^)
27+
$(subst Test ,Test&& ,$^)
2828

2929
prepare:
3030
mkdir -p $(addprefix $(BINTEST)/,$(TESTDIRS))

tests/unit/techmap/libparseTest.cc

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
#include <gtest/gtest.h>
2+
#include "passes/techmap/libparse.h"
3+
4+
YOSYS_NAMESPACE_BEGIN
5+
6+
namespace RTLIL {
7+
8+
class TechmapLibparseTest : public testing::Test {
9+
protected:
10+
TechmapLibparseTest() {
11+
if (log_files.empty()) log_files.emplace_back(stdout);
12+
}
13+
void checkAll(std::initializer_list<std::string> expressions, std::string expected) {
14+
for (const auto& e : expressions) {
15+
auto helper = LibertyExpression::Lexer(e);
16+
auto tree_s = LibertyExpression::parse(helper).str();
17+
EXPECT_EQ(tree_s, expected);
18+
}
19+
}
20+
};
21+
TEST_F(TechmapLibparseTest, LibertyExpressionSpace)
22+
{
23+
checkAll({
24+
"x",
25+
"x ",
26+
" x",
27+
" x ",
28+
" x ",
29+
}, "(pin \"x\")");
30+
31+
checkAll({
32+
"x y",
33+
" x y ",
34+
"x (y)",
35+
" x (y) ",
36+
"(x) y",
37+
" (x) y ",
38+
39+
"x & y",
40+
"x&y",
41+
"x &y",
42+
"x& y",
43+
" x&y ",
44+
"x & (y)",
45+
"x&(y)",
46+
"x &(y)",
47+
"x& (y)",
48+
" x&(y) ",
49+
"(x) & y",
50+
"(x)&y",
51+
"(x) &y",
52+
"(x)& y",
53+
" (x)&y ",
54+
}, "(and (pin \"x\")\n"
55+
" (pin \"y\"))"
56+
);
57+
58+
checkAll({
59+
"x ^ y",
60+
"x^y",
61+
"x ^y",
62+
"x^ y",
63+
" x^y ",
64+
}, "(xor (pin \"x\")\n"
65+
" (pin \"y\"))"
66+
);
67+
checkAll({
68+
"x !y",
69+
" x !y ",
70+
"x & !y",
71+
"x&!y",
72+
"x &!y",
73+
"x& !y",
74+
" x&!y ",
75+
"x y'",
76+
" x y' ",
77+
"x & y'",
78+
"x&y'",
79+
"x &y'",
80+
"x& y'",
81+
" x&y' ",
82+
}, "(and (pin \"x\")\n"
83+
" (not (pin \"y\")))"
84+
);
85+
}
86+
}
87+
88+
YOSYS_NAMESPACE_END

0 commit comments

Comments
 (0)