summaryrefslogtreecommitdiff
path: root/passes/abc/vlparse.cc
diff options
context:
space:
mode:
authorClifford Wolf <clifford@clifford.at>2013-01-05 11:13:26 +0100
committerClifford Wolf <clifford@clifford.at>2013-01-05 11:13:26 +0100
commit7764d0ba1dcf064ae487ee985c43083a0909e7f4 (patch)
tree18c05b8729df381af71b707748ce1d605e0df764 /passes/abc/vlparse.cc
initial import
Diffstat (limited to 'passes/abc/vlparse.cc')
-rw-r--r--passes/abc/vlparse.cc198
1 files changed, 198 insertions, 0 deletions
diff --git a/passes/abc/vlparse.cc b/passes/abc/vlparse.cc
new file mode 100644
index 00000000..5c0cb7e2
--- /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;
+}
+