32 using namespace Yosys;
49 if (child->id == name)
64 fprintf(stderr,
"Automatically added to blacklist: %s\n", path.c_str());
69 fprintf(f,
"%s%s", indent.c_str(),
id.c_str());
72 for (
size_t i = 0; i <
args.size(); i++)
73 fprintf(f,
"%s%s", i > 0 ?
", " :
"",
args[i].c_str());
77 fprintf(f,
" : %s",
value.c_str());
80 for (
size_t i = 0; i <
children.size(); i++)
82 fprintf(f,
"%s}\n", indent.c_str());
93 }
while (c ==
' ' || c ==
'\t' || c ==
'\r');
95 if ((
'a' <= c && c <=
'z') || (
'A' <= c && c <=
'Z') || (
'0' <= c && c <=
'9') || c ==
'_' || c ==
'-' || c ==
'+' || c ==
'.') {
99 if ((
'a' <= c && c <=
'z') || (
'A' <= c && c <=
'Z') || (
'0' <= c && c <=
'9') || c ==
'_' || c ==
'-' || c ==
'+' || c ==
'.')
127 while (c > 0 && (last_c !=
'*' || c !=
'/')) {
134 }
else if (c ==
'/') {
135 while (c > 0 && c !=
'\n')
171 int tok =
lexer(str);
176 if (tok ==
'}' || tok < 0)
192 if (tok ==
':' && ast->
value.empty()) {
209 ast->
args.push_back(arg);
241 fprintf(stderr,
"Syntax error in line %d.\n",
line);
247 #define CHECK_NV(result, check) \
249 auto _R = (result); \
251 fprintf(stderr, "Error from '%s' (%ld %s) in %s:%d.\n", \
252 #result, (long int)_R, #check, __FILE__, __LINE__); \
257 #define CHECK_COND(result) \
260 fprintf(stderr, "Error from '%s' in %s:%d.\n", \
261 #result, __FILE__, __LINE__); \
272 fprintf(stderr,
"Error: expected to find `%s' node.\n", name);
276 std::string func2vl(std::string str)
278 for (
size_t pos = str.find_first_of(
"\" \t"); pos != std::string::npos; pos = str.find_first_of(
"\" \t")) {
279 char c_left = pos > 0 ? str[pos-1] :
' ';
280 char c_right = pos+1 < str.size() ? str[pos+1] :
' ';
281 if (std::string(
"\" \t*+").
find(c_left) != std::string::npos)
283 else if (std::string(
"\" \t*+").
find(c_right) != std::string::npos)
289 std::vector<size_t> group_start;
290 for (
size_t pos = 0; pos < str.size(); pos++) {
292 group_start.push_back(pos);
293 if (str[pos] ==
')' && group_start.size() > 0) {
294 if (pos+1 < str.size() && str[pos+1] ==
'\'') {
295 std::string group = str.substr(group_start.back(), pos-group_start.back()+1);
296 str[group_start.back()] =
'~';
297 str.replace(group_start.back()+1, group.size(), group);
300 group_start.pop_back();
302 if (str[pos] ==
'\'' && pos > 0) {
303 size_t start = str.find_last_of(
"()'*+^&| ", pos-1)+1;
304 std::string group = str.substr(start, pos-start);
306 str.replace(start+1, group.size(), group);
317 void event2vl(
LibertyAst *ast, std::string &edge, std::string &expr)
323 expr = func2vl(ast->
value);
324 if (expr.size() > 0 && expr[0] ==
'~')
325 edge =
"negedge " + expr.substr(1);
327 edge =
"posedge " + expr;
331 void clear_preset_var(std::string
var, std::string type)
333 if (type.find(
'L') != std::string::npos) {
334 printf(
" %s <= 0;\n", var.c_str());
337 if (type.find(
'H') != std::string::npos) {
338 printf(
" %s <= 1;\n", var.c_str());
341 if (type.find(
'T') != std::string::npos) {
342 printf(
" %s <= ~%s;\n", var.c_str(), var.c_str());
345 if (type.find(
'X') != std::string::npos) {
346 printf(
" %s <= 'bx;\n", var.c_str());
353 if (ast->
find(
"statetable") !=
NULL)
356 CHECK_NV(ast->
args.size(), == 1);
357 printf(
"module %s (", ast->
args[0].c_str());
360 if (child->id !=
"pin")
362 CHECK_NV(child->args.size(), == 1);
363 printf(
"%s%s", first ?
"" :
", ", child->args[0].c_str());
369 if (child->id !=
"ff" && child->id !=
"latch")
373 for (
auto arg : child->args) {
374 printf(
"%s%s", first ?
"" :
", ", arg.c_str());
381 if (child->id !=
"pin")
383 CHECK_NV(child->args.size(), == 1);
384 LibertyAst *dir = find_non_null(child,
"direction");
386 printf(
" %s %s;\n", dir->value.c_str(), child->args[0].c_str());
388 printf(
" assign %s = %s; // %s\n", child->args[0].c_str(), func2vl(func->
value).c_str(), func->
value.c_str());
393 if (child->id !=
"ff" || child->args.size() != 2)
396 std::string iq_var = child->
args[0];
397 std::string iqn_var = child->args[1];
399 std::string clock_edge, clock_expr;
400 event2vl(child->find(
"clocked_on"), clock_edge, clock_expr);
402 std::string clear_edge, clear_expr;
403 event2vl(child->find(
"clear"), clear_edge, clear_expr);
405 std::string preset_edge, preset_expr;
406 event2vl(child->find(
"preset"), preset_edge, preset_expr);
408 std::string edge =
"";
409 if (!clock_edge.empty())
410 edge += (edge.empty() ?
"" :
", ") + clock_edge;
411 if (!clear_edge.empty())
412 edge += (edge.empty() ?
"" :
", ") + clear_edge;
413 if (!preset_edge.empty())
414 edge += (edge.empty() ?
"" :
", ") + preset_edge;
419 printf(
" always @(%s) begin\n", edge.c_str());
421 const char *else_prefix =
"";
422 if (!clear_expr.empty() && !preset_expr.empty()) {
423 printf(
" %sif ((%s) && (%s)) begin\n", else_prefix, clear_expr.c_str(), preset_expr.c_str());
424 clear_preset_var(iq_var, find_non_null(child,
"clear_preset_var1")->value);
425 clear_preset_var(iqn_var, find_non_null(child,
"clear_preset_var2")->value);
427 else_prefix =
"else ";
429 if (!clear_expr.empty()) {
430 printf(
" %sif (%s) begin\n", else_prefix, clear_expr.c_str());
431 printf(
" %s <= 0;\n", iq_var.c_str());
432 printf(
" %s <= 1;\n", iqn_var.c_str());
434 else_prefix =
"else ";
436 if (!preset_expr.empty()) {
437 printf(
" %sif (%s) begin\n", else_prefix, preset_expr.c_str());
438 printf(
" %s <= 1;\n", iq_var.c_str());
439 printf(
" %s <= 0;\n", iqn_var.c_str());
441 else_prefix =
"else ";
444 printf(
" %sbegin\n", else_prefix);
445 std::string expr = find_non_null(child,
"next_state")->value;
446 printf(
" // %s\n", expr.c_str());
447 printf(
" %s <= %s;\n", iq_var.c_str(), func2vl(expr).c_str());
448 printf(
" %s <= ~(%s);\n", iqn_var.c_str(), func2vl(expr).c_str());
457 if (child->id !=
"latch" || child->args.size() != 2)
460 std::string iq_var = child->args[0];
461 std::string iqn_var = child->args[1];
463 std::string enable_edge, enable_expr;
464 event2vl(child->find(
"enable"), enable_edge, enable_expr);
466 std::string clear_edge, clear_expr;
467 event2vl(child->find(
"clear"), clear_edge, clear_expr);
469 std::string preset_edge, preset_expr;
470 event2vl(child->find(
"preset"), preset_edge, preset_expr);
472 printf(
" always @* begin\n");
474 const char *else_prefix =
"";
475 if (!clear_expr.empty() && !preset_expr.empty()) {
476 printf(
" %sif ((%s) && (%s)) begin\n", else_prefix, clear_expr.c_str(), preset_expr.c_str());
477 clear_preset_var(iq_var, find_non_null(child,
"clear_preset_var1")->value);
478 clear_preset_var(iqn_var, find_non_null(child,
"clear_preset_var2")->value);
480 else_prefix =
"else ";
482 if (!clear_expr.empty()) {
483 printf(
" %sif (%s) begin\n", else_prefix, clear_expr.c_str());
484 printf(
" %s <= 0;\n", iq_var.c_str());
485 printf(
" %s <= 1;\n", iqn_var.c_str());
487 else_prefix =
"else ";
489 if (!preset_expr.empty()) {
490 printf(
" %sif (%s) begin\n", else_prefix, preset_expr.c_str());
491 printf(
" %s <= 1;\n", iq_var.c_str());
492 printf(
" %s <= 0;\n", iqn_var.c_str());
494 else_prefix =
"else ";
496 if (!enable_expr.empty()) {
497 printf(
" %sif (%s) begin\n", else_prefix, enable_expr.c_str());
498 std::string expr = find_non_null(child,
"data_in")->value;
499 printf(
" %s <= %s;\n", iq_var.c_str(), func2vl(expr).c_str());
500 printf(
" %s <= ~(%s);\n", iqn_var.c_str(), func2vl(expr).c_str());
502 else_prefix =
"else ";
508 printf(
"endmodule\n");
513 CHECK_COND(ast->
id ==
"library");
516 if (child->id ==
"cell" && !child->find(
"dont_use"))
517 gen_verilogsim_cell(child);
522 fprintf(stderr,
"Usage: filterlib [rules-file [liberty-file]]\n");
523 fprintf(stderr,
" or: filterlib -verilogsim [liberty-file]\n");
527 int main(
int argc,
char **argv)
529 bool flag_verilogsim =
false;
536 if (!strcmp(argv[1],
"-verilogsim"))
537 flag_verilogsim =
true;
538 if (!strcmp(argv[1],
"-") || !strcmp(argv[1],
"-verilogsim"))
563 FILE *f = fopen(argv[1],
"r");
565 fprintf(stderr,
"Can't open rules file `%s'.\n", argv[1]);
570 while (fgets(buffer, 1024, f) !=
NULL)
574 for (
char *p = buffer; *p; p++)
576 if (*p ==
'-' || *p ==
'+') {
582 if (*p ==
' ' || *p ==
'\t' || *p ==
'\r' || *p ==
'\n' || *p ==
'#') {
601 fprintf(stderr,
"Syntax error in rules file:\n%s", buffer);
608 std::istream *f = &std::cin;
611 std::ifstream *ff =
new std::ifstream;
615 fprintf(stderr,
"Can't open liberty file `%s'.\n", argv[2]);
624 gen_verilogsim(
parser.ast);
void log_error(const char *format,...)
std::vector< std::string > args
void dump(FILE *f, std::string indent="", std::string path="", bool path_ok=false)
USING_YOSYS_NAMESPACE int main(int argc, char **argv)
static bool find(V &ts, const T &t)
std::string id(RTLIL::IdString internal_id, bool may_rename=true)
int lexer(std::string &str)
static std::set< std::string > whitelist
std::vector< LibertyAst * > children
LibertyAst * find(std::string name)
static std::set< std::string > blacklist