/* * 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. * */ #include "vlparse.h" #include "kernel/log.h" #include #include 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; }