mirror of
https://github.com/YosysHQ/yosys
synced 2026-07-25 00:22:34 +00:00
Merge branch 'YosysHQ:main' into main
This commit is contained in:
commit
37806d5ea7
8 changed files with 172 additions and 16 deletions
|
|
@ -92,7 +92,7 @@ static bool parse_next_state(const LibertyAst *cell, const LibertyAst *attr, std
|
|||
auto expr = attr->value;
|
||||
auto cell_name = cell->args[0];
|
||||
|
||||
for (size_t pos = expr.find_first_of("\" \t"); pos != std::string::npos; pos = expr.find_first_of("\" \t"))
|
||||
for (size_t pos = expr.find_first_of("\"\t"); pos != std::string::npos; pos = expr.find_first_of("\"\t"))
|
||||
expr.erase(pos, 1);
|
||||
|
||||
// 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
|
|||
// the next_state variable isn't just a pin name; perhaps this is an enable?
|
||||
auto helper = LibertyExpression::Lexer(expr);
|
||||
auto tree = LibertyExpression::parse(helper);
|
||||
// log_debug("liberty expression:\n%s\n", tree.str().c_str());
|
||||
|
||||
if (tree.kind == LibertyExpression::Kind::EMPTY) {
|
||||
if (!warned_cells.count(cell_name)) {
|
||||
|
|
|
|||
|
|
@ -163,6 +163,12 @@ void LibertyAst::dump(FILE *f, sieve &blacklist, sieve &whitelist, std::string i
|
|||
}
|
||||
|
||||
#ifndef FILTERLIB
|
||||
|
||||
// binary operators excluding ' '
|
||||
bool LibertyExpression::is_nice_binop(char c) {
|
||||
return c == '*' || c == '&' || c == '^' || c == '+' || c == '|';
|
||||
}
|
||||
|
||||
// https://matklad.github.io/2020/04/13/simple-but-powerful-pratt-parsing.html
|
||||
LibertyExpression LibertyExpression::parse(Lexer &s, int min_prio) {
|
||||
if (s.empty())
|
||||
|
|
@ -201,15 +207,8 @@ LibertyExpression LibertyExpression::parse(Lexer &s, int min_prio) {
|
|||
while (true) {
|
||||
if (s.empty())
|
||||
break;
|
||||
|
||||
c = s.peek();
|
||||
|
||||
while (isspace(c)) {
|
||||
if (s.empty())
|
||||
return lhs;
|
||||
s.next();
|
||||
c = s.peek();
|
||||
}
|
||||
c = s.peek();
|
||||
|
||||
if (c == '\'') { // postfix NOT
|
||||
if (min_prio > 7)
|
||||
|
|
@ -235,13 +234,31 @@ LibertyExpression LibertyExpression::parse(Lexer &s, int min_prio) {
|
|||
lhs = std::move(n);
|
||||
|
||||
continue;
|
||||
} else if (c == '&' || c == '*') { // infix AND
|
||||
// technically space should be considered infix AND. it seems rare in practice.
|
||||
} else if (c == '&' || c == '*' || isspace(c)) { // infix AND
|
||||
if (min_prio > 3)
|
||||
break;
|
||||
s.next();
|
||||
|
||||
if (isspace(c)) {
|
||||
// Rewind past this space and any further spaces
|
||||
while (isspace(c)) {
|
||||
if (s.empty())
|
||||
return lhs;
|
||||
s.next();
|
||||
c = s.peek();
|
||||
}
|
||||
if (is_nice_binop(c)) {
|
||||
// We found a real binop, so this space wasn't an AND
|
||||
// and we just discard it as meaningless whitespace
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
// Rewind past this op
|
||||
s.next();
|
||||
}
|
||||
|
||||
auto rhs = parse(s, 4);
|
||||
if (rhs.kind == EMPTY)
|
||||
continue;
|
||||
auto n = LibertyExpression{};
|
||||
n.kind = Kind::AND;
|
||||
n.children.push_back(lhs);
|
||||
|
|
@ -306,6 +323,45 @@ bool LibertyExpression::eval(dict<std::string, bool>& values) {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string LibertyExpression::str(int indent)
|
||||
{
|
||||
std::string prefix;
|
||||
switch (kind) {
|
||||
case AND:
|
||||
prefix += "(and ";
|
||||
break;
|
||||
case OR:
|
||||
prefix += "(or ";
|
||||
break;
|
||||
case NOT:
|
||||
prefix += "(not ";
|
||||
break;
|
||||
case XOR:
|
||||
prefix += "(xor ";
|
||||
break;
|
||||
case PIN:
|
||||
prefix += "(pin \"" + name + "\"";
|
||||
break;
|
||||
case EMPTY:
|
||||
prefix += "(";
|
||||
break;
|
||||
default:
|
||||
log_assert(false);
|
||||
}
|
||||
size_t add_indent = prefix.length();
|
||||
bool first = true;
|
||||
for (auto child : children) {
|
||||
if (!first) {
|
||||
prefix += "\n" + std::string(indent + add_indent, ' ');
|
||||
}
|
||||
prefix += child.str(indent + add_indent);
|
||||
first = false;
|
||||
}
|
||||
prefix += ")";
|
||||
return prefix;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int LibertyParser::lexer(std::string &str)
|
||||
|
|
|
|||
|
|
@ -93,6 +93,9 @@ namespace Yosys
|
|||
static LibertyExpression parse(Lexer &s, int min_prio = 0);
|
||||
void get_pin_names(pool<std::string>& names);
|
||||
bool eval(dict<std::string, bool>& values);
|
||||
std::string str(int indent = 0);
|
||||
private:
|
||||
static bool is_nice_binop(char c);
|
||||
};
|
||||
|
||||
class LibertyInputStream {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue