From 00e7dec7f54eb2e4f18112e5c0007a55287fdf8e Mon Sep 17 00:00:00 2001 From: whitequark Date: Wed, 26 Aug 2020 17:29:32 +0000 Subject: Replace "ILANG" with "RTLIL" everywhere. The only difference between "RTLIL" and "ILANG" is that the latter is the text representation of the former, as opposed to the in-memory graph representation. This distinction serves no purpose but confuses people: it is not obvious that the ILANG backend writes RTLIL graphs. Passes `write_ilang` and `read_ilang` are provided as aliases to `write_rtlil` and `read_rtlil` for compatibility. --- frontends/ilang/.gitignore | 4 - frontends/ilang/Makefile.inc | 19 -- frontends/ilang/ilang_frontend.cc | 100 -------- frontends/ilang/ilang_frontend.h | 51 ---- frontends/ilang/ilang_lexer.l | 150 ------------ frontends/ilang/ilang_parser.y | 484 -------------------------------------- frontends/rpc/rpc_frontend.cc | 2 +- frontends/rtlil/.gitignore | 4 + frontends/rtlil/Makefile.inc | 19 ++ frontends/rtlil/rtlil_frontend.cc | 115 +++++++++ frontends/rtlil/rtlil_frontend.h | 51 ++++ frontends/rtlil/rtlil_lexer.l | 150 ++++++++++++ frontends/rtlil/rtlil_parser.y | 484 ++++++++++++++++++++++++++++++++++++++ 13 files changed, 824 insertions(+), 809 deletions(-) delete mode 100644 frontends/ilang/.gitignore delete mode 100644 frontends/ilang/Makefile.inc delete mode 100644 frontends/ilang/ilang_frontend.cc delete mode 100644 frontends/ilang/ilang_frontend.h delete mode 100644 frontends/ilang/ilang_lexer.l delete mode 100644 frontends/ilang/ilang_parser.y create mode 100644 frontends/rtlil/.gitignore create mode 100644 frontends/rtlil/Makefile.inc create mode 100644 frontends/rtlil/rtlil_frontend.cc create mode 100644 frontends/rtlil/rtlil_frontend.h create mode 100644 frontends/rtlil/rtlil_lexer.l create mode 100644 frontends/rtlil/rtlil_parser.y (limited to 'frontends') diff --git a/frontends/ilang/.gitignore b/frontends/ilang/.gitignore deleted file mode 100644 index f586b33c7..000000000 --- a/frontends/ilang/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -ilang_lexer.cc -ilang_parser.output -ilang_parser.tab.cc -ilang_parser.tab.hh diff --git a/frontends/ilang/Makefile.inc b/frontends/ilang/Makefile.inc deleted file mode 100644 index 6f1f0e8fc..000000000 --- a/frontends/ilang/Makefile.inc +++ /dev/null @@ -1,19 +0,0 @@ - -GENFILES += frontends/ilang/ilang_parser.tab.cc -GENFILES += frontends/ilang/ilang_parser.tab.hh -GENFILES += frontends/ilang/ilang_parser.output -GENFILES += frontends/ilang/ilang_lexer.cc - -frontends/ilang/ilang_parser.tab.cc: frontends/ilang/ilang_parser.y - $(Q) mkdir -p $(dir $@) - $(P) $(BISON) -o $@ -d -r all -b frontends/ilang/ilang_parser $< - -frontends/ilang/ilang_parser.tab.hh: frontends/ilang/ilang_parser.tab.cc - -frontends/ilang/ilang_lexer.cc: frontends/ilang/ilang_lexer.l - $(Q) mkdir -p $(dir $@) - $(P) flex -o frontends/ilang/ilang_lexer.cc $< - -OBJS += frontends/ilang/ilang_parser.tab.o frontends/ilang/ilang_lexer.o -OBJS += frontends/ilang/ilang_frontend.o - diff --git a/frontends/ilang/ilang_frontend.cc b/frontends/ilang/ilang_frontend.cc deleted file mode 100644 index 973e62f2c..000000000 --- a/frontends/ilang/ilang_frontend.cc +++ /dev/null @@ -1,100 +0,0 @@ -/* - * yosys -- Yosys Open SYnthesis Suite - * - * Copyright (C) 2012 Clifford Wolf - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * --- - * - * A very simple and straightforward frontend for the RTLIL text - * representation (as generated by the 'ilang' backend). - * - */ - -#include "ilang_frontend.h" -#include "kernel/register.h" -#include "kernel/log.h" - -void rtlil_frontend_ilang_yyerror(char const *s) -{ - YOSYS_NAMESPACE_PREFIX log_error("Parser error in line %d: %s\n", rtlil_frontend_ilang_yyget_lineno(), s); -} - -YOSYS_NAMESPACE_BEGIN - -struct IlangFrontend : public Frontend { - IlangFrontend() : Frontend("ilang", "read modules from ilang file") { } - void help() override - { - // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| - log("\n"); - log(" read_ilang [filename]\n"); - log("\n"); - log("Load modules from an ilang file to the current design. (ilang is a text\n"); - log("representation of a design in yosys's internal format.)\n"); - log("\n"); - log(" -nooverwrite\n"); - log(" ignore re-definitions of modules. (the default behavior is to\n"); - log(" create an error message if the existing module is not a blackbox\n"); - log(" module, and overwrite the existing module if it is a blackbox module.)\n"); - log("\n"); - log(" -overwrite\n"); - log(" overwrite existing modules with the same name\n"); - log("\n"); - log(" -lib\n"); - log(" only create empty blackbox modules\n"); - log("\n"); - } - void execute(std::istream *&f, std::string filename, std::vector args, RTLIL::Design *design) override - { - ILANG_FRONTEND::flag_nooverwrite = false; - ILANG_FRONTEND::flag_overwrite = false; - ILANG_FRONTEND::flag_lib = false; - - log_header(design, "Executing ILANG frontend.\n"); - - size_t argidx; - for (argidx = 1; argidx < args.size(); argidx++) { - std::string arg = args[argidx]; - if (arg == "-nooverwrite") { - ILANG_FRONTEND::flag_nooverwrite = true; - ILANG_FRONTEND::flag_overwrite = false; - continue; - } - if (arg == "-overwrite") { - ILANG_FRONTEND::flag_nooverwrite = false; - ILANG_FRONTEND::flag_overwrite = true; - continue; - } - if (arg == "-lib") { - ILANG_FRONTEND::flag_lib = true; - continue; - } - break; - } - extra_args(f, filename, args, argidx); - - log("Input filename: %s\n", filename.c_str()); - - ILANG_FRONTEND::lexin = f; - ILANG_FRONTEND::current_design = design; - rtlil_frontend_ilang_yydebug = false; - rtlil_frontend_ilang_yyrestart(NULL); - rtlil_frontend_ilang_yyparse(); - rtlil_frontend_ilang_yylex_destroy(); - } -} IlangFrontend; - -YOSYS_NAMESPACE_END - diff --git a/frontends/ilang/ilang_frontend.h b/frontends/ilang/ilang_frontend.h deleted file mode 100644 index f8a152841..000000000 --- a/frontends/ilang/ilang_frontend.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * yosys -- Yosys Open SYnthesis Suite - * - * Copyright (C) 2012 Clifford Wolf - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * --- - * - * A very simple and straightforward frontend for the RTLIL text - * representation (as generated by the 'ilang' backend). - * - */ - -#ifndef ILANG_FRONTEND_H -#define ILANG_FRONTEND_H - -#include "kernel/yosys.h" - -YOSYS_NAMESPACE_BEGIN - -namespace ILANG_FRONTEND { - extern std::istream *lexin; - extern RTLIL::Design *current_design; - extern bool flag_nooverwrite; - extern bool flag_overwrite; - extern bool flag_lib; -} - -YOSYS_NAMESPACE_END - -extern int rtlil_frontend_ilang_yydebug; -int rtlil_frontend_ilang_yylex(void); -void rtlil_frontend_ilang_yyerror(char const *s); -void rtlil_frontend_ilang_yyrestart(FILE *f); -int rtlil_frontend_ilang_yyparse(void); -int rtlil_frontend_ilang_yylex_destroy(void); -int rtlil_frontend_ilang_yyget_lineno(void); - -#endif - diff --git a/frontends/ilang/ilang_lexer.l b/frontends/ilang/ilang_lexer.l deleted file mode 100644 index 3362ed641..000000000 --- a/frontends/ilang/ilang_lexer.l +++ /dev/null @@ -1,150 +0,0 @@ -/* - * yosys -- Yosys Open SYnthesis Suite - * - * Copyright (C) 2012 Clifford Wolf - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * --- - * - * A very simple and straightforward frontend for the RTLIL text - * representation (as generated by the 'ilang' backend). - * - */ - -%{ - -#ifdef __clang__ -// bison generates code using the 'register' storage class specifier -#pragma clang diagnostic ignored "-Wdeprecated-register" -#endif - -#include -#include "frontends/ilang/ilang_frontend.h" -#include "ilang_parser.tab.hh" - -USING_YOSYS_NAMESPACE - -#define YY_INPUT(buf,result,max_size) \ - result = readsome(*ILANG_FRONTEND::lexin, buf, max_size) - -%} - -%option yylineno -%option noyywrap -%option nounput -%option prefix="rtlil_frontend_ilang_yy" - -%x STRING - -%% - -"autoidx" { return TOK_AUTOIDX; } -"module" { return TOK_MODULE; } -"attribute" { return TOK_ATTRIBUTE; } -"parameter" { return TOK_PARAMETER; } -"signed" { return TOK_SIGNED; } -"real" { return TOK_REAL; } -"wire" { return TOK_WIRE; } -"memory" { return TOK_MEMORY; } -"width" { return TOK_WIDTH; } -"upto" { return TOK_UPTO; } -"offset" { return TOK_OFFSET; } -"size" { return TOK_SIZE; } -"input" { return TOK_INPUT; } -"output" { return TOK_OUTPUT; } -"inout" { return TOK_INOUT; } -"cell" { return TOK_CELL; } -"connect" { return TOK_CONNECT; } -"switch" { return TOK_SWITCH; } -"case" { return TOK_CASE; } -"assign" { return TOK_ASSIGN; } -"sync" { return TOK_SYNC; } -"low" { return TOK_LOW; } -"high" { return TOK_HIGH; } -"posedge" { return TOK_POSEDGE; } -"negedge" { return TOK_NEGEDGE; } -"edge" { return TOK_EDGE; } -"always" { return TOK_ALWAYS; } -"global" { return TOK_GLOBAL; } -"init" { return TOK_INIT; } -"update" { return TOK_UPDATE; } -"process" { return TOK_PROCESS; } -"end" { return TOK_END; } - -[a-z]+ { return TOK_INVALID; } - -"\\"[^ \t\r\n]+ { rtlil_frontend_ilang_yylval.string = strdup(yytext); return TOK_ID; } -"$"[^ \t\r\n]+ { rtlil_frontend_ilang_yylval.string = strdup(yytext); return TOK_ID; } -"."[0-9]+ { rtlil_frontend_ilang_yylval.string = strdup(yytext); return TOK_ID; } - -[0-9]+'[01xzm-]* { rtlil_frontend_ilang_yylval.string = strdup(yytext); return TOK_VALUE; } --?[0-9]+ { - char *end = nullptr; - errno = 0; - long value = strtol(yytext, &end, 10); - log_assert(end == yytext + strlen(yytext)); - if (errno == ERANGE) - return TOK_INVALID; // literal out of range of long - if (value < INT_MIN || value > INT_MAX) - return TOK_INVALID; // literal out of range of int (relevant mostly for LP64 platforms) - rtlil_frontend_ilang_yylval.integer = value; - return TOK_INT; -} - -\" { BEGIN(STRING); } -\\. { yymore(); } -\" { - BEGIN(0); - char *yystr = strdup(yytext); - yystr[strlen(yytext) - 1] = 0; - int i = 0, j = 0; - while (yystr[i]) { - if (yystr[i] == '\\' && yystr[i + 1]) { - i++; - if (yystr[i] == 'n') - yystr[i] = '\n'; - else if (yystr[i] == 't') - yystr[i] = '\t'; - else if ('0' <= yystr[i] && yystr[i] <= '7') { - yystr[i] = yystr[i] - '0'; - if ('0' <= yystr[i + 1] && yystr[i + 1] <= '7') { - yystr[i + 1] = yystr[i] * 8 + yystr[i + 1] - '0'; - i++; - } - if ('0' <= yystr[i + 1] && yystr[i + 1] <= '7') { - yystr[i + 1] = yystr[i] * 8 + yystr[i + 1] - '0'; - i++; - } - } - } - yystr[j++] = yystr[i++]; - } - yystr[j] = 0; - rtlil_frontend_ilang_yylval.string = yystr; - return TOK_STRING; -} -. { yymore(); } - -"#"[^\n]* /* ignore comments */ -[ \t] /* ignore non-newline whitespaces */ -[\r\n]+ { return TOK_EOL; } - -. { return *yytext; } - -%% - -// this is a hack to avoid the 'yyinput defined but not used' error msgs -void *rtlil_frontend_ilang_avoid_input_warnings() { - return (void*)&yyinput; -} diff --git a/frontends/ilang/ilang_parser.y b/frontends/ilang/ilang_parser.y deleted file mode 100644 index 879ef4af9..000000000 --- a/frontends/ilang/ilang_parser.y +++ /dev/null @@ -1,484 +0,0 @@ -/* - * yosys -- Yosys Open SYnthesis Suite - * - * Copyright (C) 2012 Clifford Wolf - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * --- - * - * A very simple and straightforward frontend for the RTLIL text - * representation (as generated by the 'ilang' backend). - * - */ - -%{ -#include -#include "frontends/ilang/ilang_frontend.h" -YOSYS_NAMESPACE_BEGIN -namespace ILANG_FRONTEND { - std::istream *lexin; - RTLIL::Design *current_design; - RTLIL::Module *current_module; - RTLIL::Wire *current_wire; - RTLIL::Memory *current_memory; - RTLIL::Cell *current_cell; - RTLIL::Process *current_process; - std::vector*> switch_stack; - std::vector case_stack; - dict attrbuf; - bool flag_nooverwrite, flag_overwrite, flag_lib; - bool delete_current_module; -} -using namespace ILANG_FRONTEND; -YOSYS_NAMESPACE_END -USING_YOSYS_NAMESPACE -%} - -%define api.prefix {rtlil_frontend_ilang_yy} - -/* The union is defined in the header, so we need to provide all the - * includes it requires - */ -%code requires { -#include -#include -#include "frontends/ilang/ilang_frontend.h" -} - -%union { - char *string; - int integer; - YOSYS_NAMESPACE_PREFIX RTLIL::Const *data; - YOSYS_NAMESPACE_PREFIX RTLIL::SigSpec *sigspec; - std::vector *rsigspec; -} - -%token TOK_ID TOK_VALUE TOK_STRING -%token TOK_INT -%token TOK_AUTOIDX TOK_MODULE TOK_WIRE TOK_WIDTH TOK_INPUT TOK_OUTPUT TOK_INOUT -%token TOK_CELL TOK_CONNECT TOK_SWITCH TOK_CASE TOK_ASSIGN TOK_SYNC -%token TOK_LOW TOK_HIGH TOK_POSEDGE TOK_NEGEDGE TOK_EDGE TOK_ALWAYS TOK_GLOBAL TOK_INIT -%token TOK_UPDATE TOK_PROCESS TOK_END TOK_INVALID TOK_EOL TOK_OFFSET -%token TOK_PARAMETER TOK_ATTRIBUTE TOK_MEMORY TOK_SIZE TOK_SIGNED TOK_REAL TOK_UPTO - -%type sigspec_list_reversed -%type sigspec sigspec_list -%type sync_type -%type constant - -%expect 0 -%debug - -%% - -input: - optional_eol { - attrbuf.clear(); - } design { - if (attrbuf.size() != 0) - rtlil_frontend_ilang_yyerror("dangling attribute"); - }; - -EOL: - optional_eol TOK_EOL; - -optional_eol: - optional_eol TOK_EOL | /* empty */; - -design: - design module | - design attr_stmt | - design autoidx_stmt | - /* empty */; - -module: - TOK_MODULE TOK_ID EOL { - delete_current_module = false; - if (current_design->has($2)) { - RTLIL::Module *existing_mod = current_design->module($2); - if (!flag_overwrite && (flag_lib || (attrbuf.count(ID::blackbox) && attrbuf.at(ID::blackbox).as_bool()))) { - log("Ignoring blackbox re-definition of module %s.\n", $2); - delete_current_module = true; - } else if (!flag_nooverwrite && !flag_overwrite && !existing_mod->get_bool_attribute(ID::blackbox)) { - rtlil_frontend_ilang_yyerror(stringf("ilang error: redefinition of module %s.", $2).c_str()); - } else if (flag_nooverwrite) { - log("Ignoring re-definition of module %s.\n", $2); - delete_current_module = true; - } else { - log("Replacing existing%s module %s.\n", existing_mod->get_bool_attribute(ID::blackbox) ? " blackbox" : "", $2); - current_design->remove(existing_mod); - } - } - current_module = new RTLIL::Module; - current_module->name = $2; - current_module->attributes = attrbuf; - if (!delete_current_module) - current_design->add(current_module); - attrbuf.clear(); - free($2); - } module_body TOK_END { - if (attrbuf.size() != 0) - rtlil_frontend_ilang_yyerror("dangling attribute"); - current_module->fixup_ports(); - if (delete_current_module) - delete current_module; - else if (flag_lib) - current_module->makeblackbox(); - current_module = nullptr; - } EOL; - -module_body: - module_body module_stmt | - /* empty */; - -module_stmt: - param_stmt | param_defval_stmt | attr_stmt | wire_stmt | memory_stmt | cell_stmt | proc_stmt | conn_stmt; - -param_stmt: - TOK_PARAMETER TOK_ID EOL { - current_module->avail_parameters($2); - free($2); - }; - -param_defval_stmt: - TOK_PARAMETER TOK_ID constant EOL { - current_module->avail_parameters($2); - current_module->parameter_default_values[$2] = *$3; - free($2); - }; - -attr_stmt: - TOK_ATTRIBUTE TOK_ID constant EOL { - attrbuf[$2] = *$3; - delete $3; - free($2); - }; - -autoidx_stmt: - TOK_AUTOIDX TOK_INT EOL { - autoidx = max(autoidx, $2); - }; - -wire_stmt: - TOK_WIRE { - current_wire = current_module->addWire("$__ilang_frontend_tmp__"); - current_wire->attributes = attrbuf; - attrbuf.clear(); - } wire_options TOK_ID EOL { - if (current_module->wire($4) != nullptr) - rtlil_frontend_ilang_yyerror(stringf("ilang error: redefinition of wire %s.", $4).c_str()); - current_module->rename(current_wire, $4); - free($4); - }; - -wire_options: - wire_options TOK_WIDTH TOK_INT { - current_wire->width = $3; - } | - wire_options TOK_WIDTH TOK_INVALID { - rtlil_frontend_ilang_yyerror("ilang error: invalid wire width"); - } | - wire_options TOK_UPTO { - current_wire->upto = true; - } | - wire_options TOK_SIGNED { - current_wire->is_signed = true; - } | - wire_options TOK_OFFSET TOK_INT { - current_wire->start_offset = $3; - } | - wire_options TOK_INPUT TOK_INT { - current_wire->port_id = $3; - current_wire->port_input = true; - current_wire->port_output = false; - } | - wire_options TOK_OUTPUT TOK_INT { - current_wire->port_id = $3; - current_wire->port_input = false; - current_wire->port_output = true; - } | - wire_options TOK_INOUT TOK_INT { - current_wire->port_id = $3; - current_wire->port_input = true; - current_wire->port_output = true; - } | - /* empty */; - -memory_stmt: - TOK_MEMORY { - current_memory = new RTLIL::Memory; - current_memory->attributes = attrbuf; - attrbuf.clear(); - } memory_options TOK_ID EOL { - if (current_module->memories.count($4) != 0) - rtlil_frontend_ilang_yyerror(stringf("ilang error: redefinition of memory %s.", $4).c_str()); - current_memory->name = $4; - current_module->memories[$4] = current_memory; - free($4); - }; - -memory_options: - memory_options TOK_WIDTH TOK_INT { - current_memory->width = $3; - } | - memory_options TOK_SIZE TOK_INT { - current_memory->size = $3; - } | - memory_options TOK_OFFSET TOK_INT { - current_memory->start_offset = $3; - } | - /* empty */; - -cell_stmt: - TOK_CELL TOK_ID TOK_ID EOL { - if (current_module->cell($3) != nullptr) - rtlil_frontend_ilang_yyerror(stringf("ilang error: redefinition of cell %s.", $3).c_str()); - current_cell = current_module->addCell($3, $2); - current_cell->attributes = attrbuf; - attrbuf.clear(); - free($2); - free($3); - } cell_body TOK_END EOL; - -cell_body: - cell_body TOK_PARAMETER TOK_ID constant EOL { - current_cell->parameters[$3] = *$4; - free($3); - delete $4; - } | - cell_body TOK_PARAMETER TOK_SIGNED TOK_ID constant EOL { - current_cell->parameters[$4] = *$5; - current_cell->parameters[$4].flags |= RTLIL::CONST_FLAG_SIGNED; - free($4); - delete $5; - } | - cell_body TOK_PARAMETER TOK_REAL TOK_ID constant EOL { - current_cell->parameters[$4] = *$5; - current_cell->parameters[$4].flags |= RTLIL::CONST_FLAG_REAL; - free($4); - delete $5; - } | - cell_body TOK_CONNECT TOK_ID sigspec EOL { - if (current_cell->hasPort($3)) - rtlil_frontend_ilang_yyerror(stringf("ilang error: redefinition of cell port %s.", $3).c_str()); - current_cell->setPort($3, *$4); - delete $4; - free($3); - } | - /* empty */; - -proc_stmt: - TOK_PROCESS TOK_ID EOL { - if (current_module->processes.count($2) != 0) - rtlil_frontend_ilang_yyerror(stringf("ilang error: redefinition of process %s.", $2).c_str()); - current_process = new RTLIL::Process; - current_process->name = $2; - current_process->attributes = attrbuf; - current_module->processes[$2] = current_process; - switch_stack.clear(); - switch_stack.push_back(¤t_process->root_case.switches); - case_stack.clear(); - case_stack.push_back(¤t_process->root_case); - attrbuf.clear(); - free($2); - } case_body sync_list TOK_END EOL; - -switch_stmt: - TOK_SWITCH sigspec EOL { - RTLIL::SwitchRule *rule = new RTLIL::SwitchRule; - rule->signal = *$2; - rule->attributes = attrbuf; - switch_stack.back()->push_back(rule); - attrbuf.clear(); - delete $2; - } attr_list switch_body TOK_END EOL; - -attr_list: - /* empty */ | - attr_list attr_stmt; - -switch_body: - switch_body TOK_CASE { - RTLIL::CaseRule *rule = new RTLIL::CaseRule; - rule->attributes = attrbuf; - switch_stack.back()->back()->cases.push_back(rule); - switch_stack.push_back(&rule->switches); - case_stack.push_back(rule); - attrbuf.clear(); - } compare_list EOL case_body { - switch_stack.pop_back(); - case_stack.pop_back(); - } | - /* empty */; - -compare_list: - sigspec { - case_stack.back()->compare.push_back(*$1); - delete $1; - } | - compare_list ',' sigspec { - case_stack.back()->compare.push_back(*$3); - delete $3; - } | - /* empty */; - -case_body: - case_body attr_stmt | - case_body switch_stmt | - case_body assign_stmt | - /* empty */; - -assign_stmt: - TOK_ASSIGN sigspec sigspec EOL { - if (attrbuf.size() != 0) - rtlil_frontend_ilang_yyerror("dangling attribute"); - case_stack.back()->actions.push_back(RTLIL::SigSig(*$2, *$3)); - delete $2; - delete $3; - }; - -sync_list: - sync_list TOK_SYNC sync_type sigspec EOL { - RTLIL::SyncRule *rule = new RTLIL::SyncRule; - rule->type = RTLIL::SyncType($3); - rule->signal = *$4; - current_process->syncs.push_back(rule); - delete $4; - } update_list | - sync_list TOK_SYNC TOK_ALWAYS EOL { - RTLIL::SyncRule *rule = new RTLIL::SyncRule; - rule->type = RTLIL::SyncType::STa; - rule->signal = RTLIL::SigSpec(); - current_process->syncs.push_back(rule); - } update_list | - sync_list TOK_SYNC TOK_GLOBAL EOL { - RTLIL::SyncRule *rule = new RTLIL::SyncRule; - rule->type = RTLIL::SyncType::STg; - rule->signal = RTLIL::SigSpec(); - current_process->syncs.push_back(rule); - } update_list | - sync_list TOK_SYNC TOK_INIT EOL { - RTLIL::SyncRule *rule = new RTLIL::SyncRule; - rule->type = RTLIL::SyncType::STi; - rule->signal = RTLIL::SigSpec(); - current_process->syncs.push_back(rule); - } update_list | - /* empty */; - -sync_type: - TOK_LOW { $$ = RTLIL::ST0; } | - TOK_HIGH { $$ = RTLIL::ST1; } | - TOK_POSEDGE { $$ = RTLIL::STp; } | - TOK_NEGEDGE { $$ = RTLIL::STn; } | - TOK_EDGE { $$ = RTLIL::STe; }; - -update_list: - update_list TOK_UPDATE sigspec sigspec EOL { - current_process->syncs.back()->actions.push_back(RTLIL::SigSig(*$3, *$4)); - delete $3; - delete $4; - } | - /* empty */; - -constant: - TOK_VALUE { - char *ep; - int width = strtol($1, &ep, 10); - std::list bits; - while (*(++ep) != 0) { - RTLIL::State bit = RTLIL::Sx; - switch (*ep) { - case '0': bit = RTLIL::S0; break; - case '1': bit = RTLIL::S1; break; - case 'x': bit = RTLIL::Sx; break; - case 'z': bit = RTLIL::Sz; break; - case '-': bit = RTLIL::Sa; break; - case 'm': bit = RTLIL::Sm; break; - } - bits.push_front(bit); - } - if (bits.size() == 0) - bits.push_back(RTLIL::Sx); - while ((int)bits.size() < width) { - RTLIL::State bit = bits.back(); - if (bit == RTLIL::S1) - bit = RTLIL::S0; - bits.push_back(bit); - } - while ((int)bits.size() > width) - bits.pop_back(); - $$ = new RTLIL::Const; - for (auto it = bits.begin(); it != bits.end(); it++) - $$->bits.push_back(*it); - free($1); - } | - TOK_INT { - $$ = new RTLIL::Const($1, 32); - } | - TOK_STRING { - $$ = new RTLIL::Const($1); - free($1); - }; - -sigspec: - constant { - $$ = new RTLIL::SigSpec(*$1); - delete $1; - } | - TOK_ID { - if (current_module->wire($1) == nullptr) - rtlil_frontend_ilang_yyerror(stringf("ilang error: wire %s not found", $1).c_str()); - $$ = new RTLIL::SigSpec(current_module->wire($1)); - free($1); - } | - sigspec '[' TOK_INT ']' { - if ($3 >= $1->size() || $3 < 0) - rtlil_frontend_ilang_yyerror("bit index out of range"); - $$ = new RTLIL::SigSpec($1->extract($3)); - delete $1; - } | - sigspec '[' TOK_INT ':' TOK_INT ']' { - if ($3 >= $1->size() || $3 < 0 || $3 < $5) - rtlil_frontend_ilang_yyerror("invalid slice"); - $$ = new RTLIL::SigSpec($1->extract($5, $3 - $5 + 1)); - delete $1; - } | - '{' sigspec_list '}' { - $$ = $2; - }; - -sigspec_list_reversed: - sigspec_list_reversed sigspec { - $$->push_back(*$2); - delete $2; - } | - /* empty */ { - $$ = new std::vector; - }; - -sigspec_list: sigspec_list_reversed { - $$ = new RTLIL::SigSpec; - for (auto it = $1->rbegin(); it != $1->rend(); it++) - $$->append(*it); - delete $1; - }; - -conn_stmt: - TOK_CONNECT sigspec sigspec EOL { - if (attrbuf.size() != 0) - rtlil_frontend_ilang_yyerror("dangling attribute"); - current_module->connect(*$2, *$3); - delete $2; - delete $3; - }; diff --git a/frontends/rpc/rpc_frontend.cc b/frontends/rpc/rpc_frontend.cc index 6d72cbff5..5a40001cb 100644 --- a/frontends/rpc/rpc_frontend.cc +++ b/frontends/rpc/rpc_frontend.cc @@ -378,7 +378,7 @@ struct RpcFrontend : public Pass { log(" -> {\"method\": \"derive\", \"module\": \", \"parameters\": {\n"); log(" \"\": {\"type\": \"[unsigned|signed|string|real]\",\n"); log(" \"value\": \"\"}, ...}}\n"); - log(" <- {\"frontend\": \"[ilang|verilog|...]\",\"source\": \"\"}}\n"); + log(" <- {\"frontend\": \"[rtlil|verilog|...]\",\"source\": \"\"}}\n"); log(" <- {\"error\": \"\"}\n"); log(" request for the module to be derived for a specific set of\n"); log(" parameters. starts with \\ for named parameters, and with $\n"); diff --git a/frontends/rtlil/.gitignore b/frontends/rtlil/.gitignore new file mode 100644 index 000000000..d4a322756 --- /dev/null +++ b/frontends/rtlil/.gitignore @@ -0,0 +1,4 @@ +rtlil_lexer.cc +rtlil_parser.output +rtlil_parser.tab.cc +rtlil_parser.tab.hh diff --git a/frontends/rtlil/Makefile.inc b/frontends/rtlil/Makefile.inc new file mode 100644 index 000000000..d0c0cfcf8 --- /dev/null +++ b/frontends/rtlil/Makefile.inc @@ -0,0 +1,19 @@ + +GENFILES += frontends/rtlil/rtlil_parser.tab.cc +GENFILES += frontends/rtlil/rtlil_parser.tab.hh +GENFILES += frontends/rtlil/rtlil_parser.output +GENFILES += frontends/rtlil/rtlil_lexer.cc + +frontends/rtlil/rtlil_parser.tab.cc: frontends/rtlil/rtlil_parser.y + $(Q) mkdir -p $(dir $@) + $(P) $(BISON) -o $@ -d -r all -b frontends/rtlil/rtlil_parser $< + +frontends/rtlil/rtlil_parser.tab.hh: frontends/rtlil/rtlil_parser.tab.cc + +frontends/rtlil/rtlil_lexer.cc: frontends/rtlil/rtlil_lexer.l + $(Q) mkdir -p $(dir $@) + $(P) flex -o frontends/rtlil/rtlil_lexer.cc $< + +OBJS += frontends/rtlil/rtlil_parser.tab.o frontends/rtlil/rtlil_lexer.o +OBJS += frontends/rtlil/rtlil_frontend.o + diff --git a/frontends/rtlil/rtlil_frontend.cc b/frontends/rtlil/rtlil_frontend.cc new file mode 100644 index 000000000..00c34175e --- /dev/null +++ b/frontends/rtlil/rtlil_frontend.cc @@ -0,0 +1,115 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 Clifford Wolf + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * --- + * + * A very simple and straightforward frontend for the RTLIL text + * representation. + * + */ + +#include "rtlil_frontend.h" +#include "kernel/register.h" +#include "kernel/log.h" + +void rtlil_frontend_yyerror(char const *s) +{ + YOSYS_NAMESPACE_PREFIX log_error("Parser error in line %d: %s\n", rtlil_frontend_yyget_lineno(), s); +} + +YOSYS_NAMESPACE_BEGIN + +struct RTLILFrontend : public Frontend { + RTLILFrontend() : Frontend("rtlil", "read modules from RTLIL file") { } + void help() override + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" read_rtlil [filename]\n"); + log("\n"); + log("Load modules from an RTLIL file to the current design. (RTLIL is a text\n"); + log("representation of a design in yosys's internal format.)\n"); + log("\n"); + log(" -nooverwrite\n"); + log(" ignore re-definitions of modules. (the default behavior is to\n"); + log(" create an error message if the existing module is not a blackbox\n"); + log(" module, and overwrite the existing module if it is a blackbox module.)\n"); + log("\n"); + log(" -overwrite\n"); + log(" overwrite existing modules with the same name\n"); + log("\n"); + log(" -lib\n"); + log(" only create empty blackbox modules\n"); + log("\n"); + } + void execute(std::istream *&f, std::string filename, std::vector args, RTLIL::Design *design) override + { + RTLIL_FRONTEND::flag_nooverwrite = false; + RTLIL_FRONTEND::flag_overwrite = false; + RTLIL_FRONTEND::flag_lib = false; + + log_header(design, "Executing RTLIL frontend.\n"); + + size_t argidx; + for (argidx = 1; argidx < args.size(); argidx++) { + std::string arg = args[argidx]; + if (arg == "-nooverwrite") { + RTLIL_FRONTEND::flag_nooverwrite = true; + RTLIL_FRONTEND::flag_overwrite = false; + continue; + } + if (arg == "-overwrite") { + RTLIL_FRONTEND::flag_nooverwrite = false; + RTLIL_FRONTEND::flag_overwrite = true; + continue; + } + if (arg == "-lib") { + RTLIL_FRONTEND::flag_lib = true; + continue; + } + break; + } + extra_args(f, filename, args, argidx); + + log("Input filename: %s\n", filename.c_str()); + + RTLIL_FRONTEND::lexin = f; + RTLIL_FRONTEND::current_design = design; + rtlil_frontend_yydebug = false; + rtlil_frontend_yyrestart(NULL); + rtlil_frontend_yyparse(); + rtlil_frontend_yylex_destroy(); + } +} RTLILFrontend; + +struct IlangFrontend : public Frontend { + IlangFrontend() : Frontend("ilang", "(deprecated) alias of read_rtlil") { } + void help() override + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log("See `help read_rtlil`.\n"); + log("\n"); + } + void execute(std::istream *&f, std::string filename, std::vector args, RTLIL::Design *design) override + { + RTLILFrontend.execute(f, filename, args, design); + } +} IlangFrontend; + +YOSYS_NAMESPACE_END + diff --git a/frontends/rtlil/rtlil_frontend.h b/frontends/rtlil/rtlil_frontend.h new file mode 100644 index 000000000..a420778b0 --- /dev/null +++ b/frontends/rtlil/rtlil_frontend.h @@ -0,0 +1,51 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 Clifford Wolf + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * --- + * + * A very simple and straightforward frontend for the RTLIL text + * representation. + * + */ + +#ifndef RTLIL_FRONTEND_H +#define RTLIL_FRONTEND_H + +#include "kernel/yosys.h" + +YOSYS_NAMESPACE_BEGIN + +namespace RTLIL_FRONTEND { + extern std::istream *lexin; + extern RTLIL::Design *current_design; + extern bool flag_nooverwrite; + extern bool flag_overwrite; + extern bool flag_lib; +} + +YOSYS_NAMESPACE_END + +extern int rtlil_frontend_yydebug; +int rtlil_frontend_yylex(void); +void rtlil_frontend_yyerror(char const *s); +void rtlil_frontend_yyrestart(FILE *f); +int rtlil_frontend_yyparse(void); +int rtlil_frontend_yylex_destroy(void); +int rtlil_frontend_yyget_lineno(void); + +#endif + diff --git a/frontends/rtlil/rtlil_lexer.l b/frontends/rtlil/rtlil_lexer.l new file mode 100644 index 000000000..295455f53 --- /dev/null +++ b/frontends/rtlil/rtlil_lexer.l @@ -0,0 +1,150 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 Clifford Wolf + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * --- + * + * A very simple and straightforward frontend for the RTLIL text + * representation. + * + */ + +%{ + +#ifdef __clang__ +// bison generates code using the 'register' storage class specifier +#pragma clang diagnostic ignored "-Wdeprecated-register" +#endif + +#include +#include "frontends/rtlil/rtlil_frontend.h" +#include "rtlil_parser.tab.hh" + +USING_YOSYS_NAMESPACE + +#define YY_INPUT(buf,result,max_size) \ + result = readsome(*RTLIL_FRONTEND::lexin, buf, max_size) + +%} + +%option yylineno +%option noyywrap +%option nounput +%option prefix="rtlil_frontend_yy" + +%x STRING + +%% + +"autoidx" { return TOK_AUTOIDX; } +"module" { return TOK_MODULE; } +"attribute" { return TOK_ATTRIBUTE; } +"parameter" { return TOK_PARAMETER; } +"signed" { return TOK_SIGNED; } +"real" { return TOK_REAL; } +"wire" { return TOK_WIRE; } +"memory" { return TOK_MEMORY; } +"width" { return TOK_WIDTH; } +"upto" { return TOK_UPTO; } +"offset" { return TOK_OFFSET; } +"size" { return TOK_SIZE; } +"input" { return TOK_INPUT; } +"output" { return TOK_OUTPUT; } +"inout" { return TOK_INOUT; } +"cell" { return TOK_CELL; } +"connect" { return TOK_CONNECT; } +"switch" { return TOK_SWITCH; } +"case" { return TOK_CASE; } +"assign" { return TOK_ASSIGN; } +"sync" { return TOK_SYNC; } +"low" { return TOK_LOW; } +"high" { return TOK_HIGH; } +"posedge" { return TOK_POSEDGE; } +"negedge" { return TOK_NEGEDGE; } +"edge" { return TOK_EDGE; } +"always" { return TOK_ALWAYS; } +"global" { return TOK_GLOBAL; } +"init" { return TOK_INIT; } +"update" { return TOK_UPDATE; } +"process" { return TOK_PROCESS; } +"end" { return TOK_END; } + +[a-z]+ { return TOK_INVALID; } + +"\\"[^ \t\r\n]+ { rtlil_frontend_yylval.string = strdup(yytext); return TOK_ID; } +"$"[^ \t\r\n]+ { rtlil_frontend_yylval.string = strdup(yytext); return TOK_ID; } +"."[0-9]+ { rtlil_frontend_yylval.string = strdup(yytext); return TOK_ID; } + +[0-9]+'[01xzm-]* { rtlil_frontend_yylval.string = strdup(yytext); return TOK_VALUE; } +-?[0-9]+ { + char *end = nullptr; + errno = 0; + long value = strtol(yytext, &end, 10); + log_assert(end == yytext + strlen(yytext)); + if (errno == ERANGE) + return TOK_INVALID; // literal out of range of long + if (value < INT_MIN || value > INT_MAX) + return TOK_INVALID; // literal out of range of int (relevant mostly for LP64 platforms) + rtlil_frontend_yylval.integer = value; + return TOK_INT; +} + +\" { BEGIN(STRING); } +\\. { yymore(); } +\" { + BEGIN(0); + char *yystr = strdup(yytext); + yystr[strlen(yytext) - 1] = 0; + int i = 0, j = 0; + while (yystr[i]) { + if (yystr[i] == '\\' && yystr[i + 1]) { + i++; + if (yystr[i] == 'n') + yystr[i] = '\n'; + else if (yystr[i] == 't') + yystr[i] = '\t'; + else if ('0' <= yystr[i] && yystr[i] <= '7') { + yystr[i] = yystr[i] - '0'; + if ('0' <= yystr[i + 1] && yystr[i + 1] <= '7') { + yystr[i + 1] = yystr[i] * 8 + yystr[i + 1] - '0'; + i++; + } + if ('0' <= yystr[i + 1] && yystr[i + 1] <= '7') { + yystr[i + 1] = yystr[i] * 8 + yystr[i + 1] - '0'; + i++; + } + } + } + yystr[j++] = yystr[i++]; + } + yystr[j] = 0; + rtlil_frontend_yylval.string = yystr; + return TOK_STRING; +} +. { yymore(); } + +"#"[^\n]* /* ignore comments */ +[ \t] /* ignore non-newline whitespaces */ +[\r\n]+ { return TOK_EOL; } + +. { return *yytext; } + +%% + +// this is a hack to avoid the 'yyinput defined but not used' error msgs +void *rtlil_frontend_avoid_input_warnings() { + return (void*)&yyinput; +} diff --git a/frontends/rtlil/rtlil_parser.y b/frontends/rtlil/rtlil_parser.y new file mode 100644 index 000000000..646489196 --- /dev/null +++ b/frontends/rtlil/rtlil_parser.y @@ -0,0 +1,484 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 Clifford Wolf + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * --- + * + * A very simple and straightforward frontend for the RTLIL text + * representation. + * + */ + +%{ +#include +#include "frontends/rtlil/rtlil_frontend.h" +YOSYS_NAMESPACE_BEGIN +namespace RTLIL_FRONTEND { + std::istream *lexin; + RTLIL::Design *current_design; + RTLIL::Module *current_module; + RTLIL::Wire *current_wire; + RTLIL::Memory *current_memory; + RTLIL::Cell *current_cell; + RTLIL::Process *current_process; + std::vector*> switch_stack; + std::vector case_stack; + dict attrbuf; + bool flag_nooverwrite, flag_overwrite, flag_lib; + bool delete_current_module; +} +using namespace RTLIL_FRONTEND; +YOSYS_NAMESPACE_END +USING_YOSYS_NAMESPACE +%} + +%define api.prefix {rtlil_frontend_yy} + +/* The union is defined in the header, so we need to provide all the + * includes it requires + */ +%code requires { +#include +#include +#include "frontends/rtlil/rtlil_frontend.h" +} + +%union { + char *string; + int integer; + YOSYS_NAMESPACE_PREFIX RTLIL::Const *data; + YOSYS_NAMESPACE_PREFIX RTLIL::SigSpec *sigspec; + std::vector *rsigspec; +} + +%token TOK_ID TOK_VALUE TOK_STRING +%token TOK_INT +%token TOK_AUTOIDX TOK_MODULE TOK_WIRE TOK_WIDTH TOK_INPUT TOK_OUTPUT TOK_INOUT +%token TOK_CELL TOK_CONNECT TOK_SWITCH TOK_CASE TOK_ASSIGN TOK_SYNC +%token TOK_LOW TOK_HIGH TOK_POSEDGE TOK_NEGEDGE TOK_EDGE TOK_ALWAYS TOK_GLOBAL TOK_INIT +%token TOK_UPDATE TOK_PROCESS TOK_END TOK_INVALID TOK_EOL TOK_OFFSET +%token TOK_PARAMETER TOK_ATTRIBUTE TOK_MEMORY TOK_SIZE TOK_SIGNED TOK_REAL TOK_UPTO + +%type sigspec_list_reversed +%type sigspec sigspec_list +%type sync_type +%type constant + +%expect 0 +%debug + +%% + +input: + optional_eol { + attrbuf.clear(); + } design { + if (attrbuf.size() != 0) + rtlil_frontend_yyerror("dangling attribute"); + }; + +EOL: + optional_eol TOK_EOL; + +optional_eol: + optional_eol TOK_EOL | /* empty */; + +design: + design module | + design attr_stmt | + design autoidx_stmt | + /* empty */; + +module: + TOK_MODULE TOK_ID EOL { + delete_current_module = false; + if (current_design->has($2)) { + RTLIL::Module *existing_mod = current_design->module($2); + if (!flag_overwrite && (flag_lib || (attrbuf.count(ID::blackbox) && attrbuf.at(ID::blackbox).as_bool()))) { + log("Ignoring blackbox re-definition of module %s.\n", $2); + delete_current_module = true; + } else if (!flag_nooverwrite && !flag_overwrite && !existing_mod->get_bool_attribute(ID::blackbox)) { + rtlil_frontend_yyerror(stringf("RTLIL error: redefinition of module %s.", $2).c_str()); + } else if (flag_nooverwrite) { + log("Ignoring re-definition of module %s.\n", $2); + delete_current_module = true; + } else { + log("Replacing existing%s module %s.\n", existing_mod->get_bool_attribute(ID::blackbox) ? " blackbox" : "", $2); + current_design->remove(existing_mod); + } + } + current_module = new RTLIL::Module; + current_module->name = $2; + current_module->attributes = attrbuf; + if (!delete_current_module) + current_design->add(current_module); + attrbuf.clear(); + free($2); + } module_body TOK_END { + if (attrbuf.size() != 0) + rtlil_frontend_yyerror("dangling attribute"); + current_module->fixup_ports(); + if (delete_current_module) + delete current_module; + else if (flag_lib) + current_module->makeblackbox(); + current_module = nullptr; + } EOL; + +module_body: + module_body module_stmt | + /* empty */; + +module_stmt: + param_stmt | param_defval_stmt | attr_stmt | wire_stmt | memory_stmt | cell_stmt | proc_stmt | conn_stmt; + +param_stmt: + TOK_PARAMETER TOK_ID EOL { + current_module->avail_parameters($2); + free($2); + }; + +param_defval_stmt: + TOK_PARAMETER TOK_ID constant EOL { + current_module->avail_parameters($2); + current_module->parameter_default_values[$2] = *$3; + free($2); + }; + +attr_stmt: + TOK_ATTRIBUTE TOK_ID constant EOL { + attrbuf[$2] = *$3; + delete $3; + free($2); + }; + +autoidx_stmt: + TOK_AUTOIDX TOK_INT EOL { + autoidx = max(autoidx, $2); + }; + +wire_stmt: + TOK_WIRE { + current_wire = current_module->addWire("$__rtlil_frontend_tmp__"); + current_wire->attributes = attrbuf; + attrbuf.clear(); + } wire_options TOK_ID EOL { + if (current_module->wire($4) != nullptr) + rtlil_frontend_yyerror(stringf("RTLIL error: redefinition of wire %s.", $4).c_str()); + current_module->rename(current_wire, $4); + free($4); + }; + +wire_options: + wire_options TOK_WIDTH TOK_INT { + current_wire->width = $3; + } | + wire_options TOK_WIDTH TOK_INVALID { + rtlil_frontend_yyerror("RTLIL error: invalid wire width"); + } | + wire_options TOK_UPTO { + current_wire->upto = true; + } | + wire_options TOK_SIGNED { + current_wire->is_signed = true; + } | + wire_options TOK_OFFSET TOK_INT { + current_wire->start_offset = $3; + } | + wire_options TOK_INPUT TOK_INT { + current_wire->port_id = $3; + current_wire->port_input = true; + current_wire->port_output = false; + } | + wire_options TOK_OUTPUT TOK_INT { + current_wire->port_id = $3; + current_wire->port_input = false; + current_wire->port_output = true; + } | + wire_options TOK_INOUT TOK_INT { + current_wire->port_id = $3; + current_wire->port_input = true; + current_wire->port_output = true; + } | + /* empty */; + +memory_stmt: + TOK_MEMORY { + current_memory = new RTLIL::Memory; + current_memory->attributes = attrbuf; + attrbuf.clear(); + } memory_options TOK_ID EOL { + if (current_module->memories.count($4) != 0) + rtlil_frontend_yyerror(stringf("RTLIL error: redefinition of memory %s.", $4).c_str()); + current_memory->name = $4; + current_module->memories[$4] = current_memory; + free($4); + }; + +memory_options: + memory_options TOK_WIDTH TOK_INT { + current_memory->width = $3; + } | + memory_options TOK_SIZE TOK_INT { + current_memory->size = $3; + } | + memory_options TOK_OFFSET TOK_INT { + current_memory->start_offset = $3; + } | + /* empty */; + +cell_stmt: + TOK_CELL TOK_ID TOK_ID EOL { + if (current_module->cell($3) != nullptr) + rtlil_frontend_yyerror(stringf("RTLIL error: redefinition of cell %s.", $3).c_str()); + current_cell = current_module->addCell($3, $2); + current_cell->attributes = attrbuf; + attrbuf.clear(); + free($2); + free($3); + } cell_body TOK_END EOL; + +cell_body: + cell_body TOK_PARAMETER TOK_ID constant EOL { + current_cell->parameters[$3] = *$4; + free($3); + delete $4; + } | + cell_body TOK_PARAMETER TOK_SIGNED TOK_ID constant EOL { + current_cell->parameters[$4] = *$5; + current_cell->parameters[$4].flags |= RTLIL::CONST_FLAG_SIGNED; + free($4); + delete $5; + } | + cell_body TOK_PARAMETER TOK_REAL TOK_ID constant EOL { + current_cell->parameters[$4] = *$5; + current_cell->parameters[$4].flags |= RTLIL::CONST_FLAG_REAL; + free($4); + delete $5; + } | + cell_body TOK_CONNECT TOK_ID sigspec EOL { + if (current_cell->hasPort($3)) + rtlil_frontend_yyerror(stringf("RTLIL error: redefinition of cell port %s.", $3).c_str()); + current_cell->setPort($3, *$4); + delete $4; + free($3); + } | + /* empty */; + +proc_stmt: + TOK_PROCESS TOK_ID EOL { + if (current_module->processes.count($2) != 0) + rtlil_frontend_yyerror(stringf("RTLIL error: redefinition of process %s.", $2).c_str()); + current_process = new RTLIL::Process; + current_process->name = $2; + current_process->attributes = attrbuf; + current_module->processes[$2] = current_process; + switch_stack.clear(); + switch_stack.push_back(¤t_process->root_case.switches); + case_stack.clear(); + case_stack.push_back(¤t_process->root_case); + attrbuf.clear(); + free($2); + } case_body sync_list TOK_END EOL; + +switch_stmt: + TOK_SWITCH sigspec EOL { + RTLIL::SwitchRule *rule = new RTLIL::SwitchRule; + rule->signal = *$2; + rule->attributes = attrbuf; + switch_stack.back()->push_back(rule); + attrbuf.clear(); + delete $2; + } attr_list switch_body TOK_END EOL; + +attr_list: + /* empty */ | + attr_list attr_stmt; + +switch_body: + switch_body TOK_CASE { + RTLIL::CaseRule *rule = new RTLIL::CaseRule; + rule->attributes = attrbuf; + switch_stack.back()->back()->cases.push_back(rule); + switch_stack.push_back(&rule->switches); + case_stack.push_back(rule); + attrbuf.clear(); + } compare_list EOL case_body { + switch_stack.pop_back(); + case_stack.pop_back(); + } | + /* empty */; + +compare_list: + sigspec { + case_stack.back()->compare.push_back(*$1); + delete $1; + } | + compare_list ',' sigspec { + case_stack.back()->compare.push_back(*$3); + delete $3; + } | + /* empty */; + +case_body: + case_body attr_stmt | + case_body switch_stmt | + case_body assign_stmt | + /* empty */; + +assign_stmt: + TOK_ASSIGN sigspec sigspec EOL { + if (attrbuf.size() != 0) + rtlil_frontend_yyerror("dangling attribute"); + case_stack.back()->actions.push_back(RTLIL::SigSig(*$2, *$3)); + delete $2; + delete $3; + }; + +sync_list: + sync_list TOK_SYNC sync_type sigspec EOL { + RTLIL::SyncRule *rule = new RTLIL::SyncRule; + rule->type = RTLIL::SyncType($3); + rule->signal = *$4; + current_process->syncs.push_back(rule); + delete $4; + } update_list | + sync_list TOK_SYNC TOK_ALWAYS EOL { + RTLIL::SyncRule *rule = new RTLIL::SyncRule; + rule->type = RTLIL::SyncType::STa; + rule->signal = RTLIL::SigSpec(); + current_process->syncs.push_back(rule); + } update_list | + sync_list TOK_SYNC TOK_GLOBAL EOL { + RTLIL::SyncRule *rule = new RTLIL::SyncRule; + rule->type = RTLIL::SyncType::STg; + rule->signal = RTLIL::SigSpec(); + current_process->syncs.push_back(rule); + } update_list | + sync_list TOK_SYNC TOK_INIT EOL { + RTLIL::SyncRule *rule = new RTLIL::SyncRule; + rule->type = RTLIL::SyncType::STi; + rule->signal = RTLIL::SigSpec(); + current_process->syncs.push_back(rule); + } update_list | + /* empty */; + +sync_type: + TOK_LOW { $$ = RTLIL::ST0; } | + TOK_HIGH { $$ = RTLIL::ST1; } | + TOK_POSEDGE { $$ = RTLIL::STp; } | + TOK_NEGEDGE { $$ = RTLIL::STn; } | + TOK_EDGE { $$ = RTLIL::STe; }; + +update_list: + update_list TOK_UPDATE sigspec sigspec EOL { + current_process->syncs.back()->actions.push_back(RTLIL::SigSig(*$3, *$4)); + delete $3; + delete $4; + } | + /* empty */; + +constant: + TOK_VALUE { + char *ep; + int width = strtol($1, &ep, 10); + std::list bits; + while (*(++ep) != 0) { + RTLIL::State bit = RTLIL::Sx; + switch (*ep) { + case '0': bit = RTLIL::S0; break; + case '1': bit = RTLIL::S1; break; + case 'x': bit = RTLIL::Sx; break; + case 'z': bit = RTLIL::Sz; break; + case '-': bit = RTLIL::Sa; break; + case 'm': bit = RTLIL::Sm; break; + } + bits.push_front(bit); + } + if (bits.size() == 0) + bits.push_back(RTLIL::Sx); + while ((int)bits.size() < width) { + RTLIL::State bit = bits.back(); + if (bit == RTLIL::S1) + bit = RTLIL::S0; + bits.push_back(bit); + } + while ((int)bits.size() > width) + bits.pop_back(); + $$ = new RTLIL::Const; + for (auto it = bits.begin(); it != bits.end(); it++) + $$->bits.push_back(*it); + free($1); + } | + TOK_INT { + $$ = new RTLIL::Const($1, 32); + } | + TOK_STRING { + $$ = new RTLIL::Const($1); + free($1); + }; + +sigspec: + constant { + $$ = new RTLIL::SigSpec(*$1); + delete $1; + } | + TOK_ID { + if (current_module->wire($1) == nullptr) + rtlil_frontend_yyerror(stringf("RTLIL error: wire %s not found", $1).c_str()); + $$ = new RTLIL::SigSpec(current_module->wire($1)); + free($1); + } | + sigspec '[' TOK_INT ']' { + if ($3 >= $1->size() || $3 < 0) + rtlil_frontend_yyerror("bit index out of range"); + $$ = new RTLIL::SigSpec($1->extract($3)); + delete $1; + } | + sigspec '[' TOK_INT ':' TOK_INT ']' { + if ($3 >= $1->size() || $3 < 0 || $3 < $5) + rtlil_frontend_yyerror("invalid slice"); + $$ = new RTLIL::SigSpec($1->extract($5, $3 - $5 + 1)); + delete $1; + } | + '{' sigspec_list '}' { + $$ = $2; + }; + +sigspec_list_reversed: + sigspec_list_reversed sigspec { + $$->push_back(*$2); + delete $2; + } | + /* empty */ { + $$ = new std::vector; + }; + +sigspec_list: sigspec_list_reversed { + $$ = new RTLIL::SigSpec; + for (auto it = $1->rbegin(); it != $1->rend(); it++) + $$->append(*it); + delete $1; + }; + +conn_stmt: + TOK_CONNECT sigspec sigspec EOL { + if (attrbuf.size() != 0) + rtlil_frontend_yyerror("dangling attribute"); + current_module->connect(*$2, *$3); + delete $2; + delete $3; + }; -- cgit v1.2.3