diff options
Diffstat (limited to 'passes/abc/vlparse.cc')
-rw-r--r-- | passes/abc/vlparse.cc | 198 |
1 files changed, 198 insertions, 0 deletions
diff --git a/passes/abc/vlparse.cc b/passes/abc/vlparse.cc new file mode 100644 index 000000000..5c0cb7e24 --- /dev/null +++ b/passes/abc/vlparse.cc @@ -0,0 +1,198 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at> + * + * 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. + * + */ + +#include "vlparse.h" +#include "kernel/log.h" +#include <stdio.h> +#include <string> + +static int lex_line, lex_tok; +static std::string lex_str; + +static int token(int tok) +{ + lex_tok = tok; +#if 0 + if (lex_tok == 256) + fprintf(stderr, "STR in line %d: >>%s<<\n", lex_line, lex_str.c_str()); + else if (tok >= 32 && tok < 255) + fprintf(stderr, "CHAR in line %d: >>%c<<\n", lex_line, lex_tok); + else + fprintf(stderr, "CHAR in line %d: %d\n", lex_line, lex_tok); +#endif + return tok; +} + +static int lex(FILE *f) +{ + int ch = getc(f); + + while (ch == ' ' || ch == '\t' || ch == '\n') { + if (ch == '\n') + lex_line++; + ch = getc(f); + } + + if (ch <= 0 || 255 < ch) + return token(lex_tok); + + if (('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z') || + ('0' <= ch && ch <= '9') || ch == '_') { + lex_str = char(ch); + while (1) { + ch = getc(f); + if (('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z') || + ('0' <= ch && ch <= '9') || ch == '_') { + lex_str += char(ch); + continue; + } + break; + } + ungetc(ch, f); + return token(256); + } + + if (ch == '/') { + ch = getc(f); + if (ch == '/') { + while (ch != '\n') + ch = getc(f); + ungetc(ch, f); + return lex(f); + } + ungetc(ch, f); + return token('/'); + } + + return token(ch); +} + +RTLIL::Design *abc_parse_verilog(FILE *f) +{ + RTLIL::Design *design = new RTLIL::Design; + RTLIL::Module *module; + RTLIL::Wire *wire; + RTLIL::Cell *cell; + + int port_count = 1; + lex_line = 1; + + // parse module header + if (lex(f) != 256 || lex_str != "module") + goto error; + if (lex(f) != 256) + goto error; + + module = new RTLIL::Module; + module->name = "\\" + lex_str; + design->modules[module->name] = module; + + if (lex(f) != '(') + goto error; + while (lex(f) != ')') { + if (lex_tok != 256 && lex_tok != ',') + goto error; + } + if (lex(f) != ';') + goto error; + + // parse module body + while (1) + { + if (lex(f) != 256) + goto error; + + if (lex_str == "endmodule") + return design; + + if (lex_str == "input" || lex_str == "output" || lex_str == "wire") + { + std::string mode = lex_str; + while (lex(f) != ';') { + if (lex_tok != 256 && lex_tok != ',') + goto error; + if (lex_tok == 256) { + // printf("%s [%s]\n", mode.c_str(), lex_str.c_str()); + wire = new RTLIL::Wire; + wire->name = "\\" + lex_str; + if (mode == "input") { + wire->port_id = port_count++; + wire->port_input = true; + } + if (mode == "output") { + wire->port_id = port_count++; + wire->port_output = true; + } + module->wires[wire->name] = wire; + } + } + } + else + { + std::string cell_type = lex_str; + + if (lex(f) != 256) + goto error; + + std::string cell_name = lex_str; + + if (lex(f) != '(') + goto error; + + // printf("cell [%s] [%s]\n", cell_type.c_str(), cell_name.c_str()); + cell = new RTLIL::Cell; + cell->type = "\\" + cell_type; + cell->name = "\\" + cell_name; + module->cells[cell->name] = cell; + + lex(f); + while (lex_tok != ')') + { + if (lex_tok != '.' || lex(f) != 256) + goto error; + + std::string cell_port = lex_str; + + if (lex(f) != '(' || lex(f) != 256) + goto error; + + std::string wire_name = lex_str; + + // printf(" [%s] <- [%s]\n", cell_port.c_str(), wire_name.c_str()); + if (module->wires.count("\\" + wire_name) == 0) + goto error; + cell->connections["\\" + cell_port] = RTLIL::SigSpec(module->wires["\\" + wire_name]); + + if (lex(f) != ')' || (lex(f) != ',' && lex_tok != ')')) + goto error; + while (lex_tok == ',') + lex(f); + } + + if (lex(f) != ';') + goto error; + } + } + +error: + log_error("Syntax error in line %d!\n", lex_line); + // delete design; + // return NULL; +} + |