diff options
-rw-r--r-- | Makefile | 8 | ||||
-rw-r--r-- | backends/smt2/smt2.cc | 4 | ||||
-rw-r--r-- | backends/smt2/smtbmc.py | 12 | ||||
-rw-r--r-- | backends/smt2/smtio.py | 29 | ||||
-rw-r--r-- | frontends/ast/ast.cc | 9 | ||||
-rw-r--r-- | frontends/ast/genrtlil.cc | 88 | ||||
-rw-r--r-- | frontends/ast/simplify.cc | 88 | ||||
-rw-r--r-- | frontends/liberty/liberty.cc | 3 | ||||
-rw-r--r-- | frontends/verific/verific.cc | 1 | ||||
-rw-r--r-- | frontends/verilog/verilog_parser.y | 13 | ||||
-rw-r--r-- | kernel/yosys.cc | 2 | ||||
-rw-r--r-- | passes/techmap/dfflibmap.cc | 12 | ||||
-rw-r--r-- | passes/techmap/libparse.cc | 15 | ||||
-rw-r--r-- | techlibs/sf2/Makefile.inc | 7 | ||||
-rw-r--r-- | techlibs/sf2/arith_map.v | 21 | ||||
-rw-r--r-- | techlibs/sf2/cells_map.v | 68 | ||||
-rw-r--r-- | techlibs/sf2/cells_sim.v | 75 | ||||
-rw-r--r-- | techlibs/sf2/synth_sf2.cc | 206 |
18 files changed, 542 insertions, 119 deletions
@@ -109,7 +109,7 @@ OBJS = kernel/version_$(GIT_REV).o # is just a symlink to your actual ABC working directory, as 'make mrproper' # will remove the 'abc' directory and you do not want to accidentally # delete your work on ABC.. -ABCREV = 14d985a +ABCREV = 4d56acf ABCPULL = 1 ABCURL ?= https://github.com/berkeley-abc/abc ABCMKARGS = CC="$(CXX)" CXX="$(CXX)" ABC_USE_LIBSTDCXX=1 @@ -359,8 +359,12 @@ ifeq ($(ENABLE_VERIFIC),1) VERIFIC_DIR ?= /usr/local/src/verific_lib_eval VERIFIC_COMPONENTS ?= verilog vhdl database util containers sdf hier_tree CXXFLAGS += $(patsubst %,-I$(VERIFIC_DIR)/%,$(VERIFIC_COMPONENTS)) -DYOSYS_ENABLE_VERIFIC +ifeq ($(OS), Darwin) +LDLIBS += $(patsubst %,$(VERIFIC_DIR)/%/*-mac.a,$(VERIFIC_COMPONENTS)) -lz +else LDLIBS += $(patsubst %,$(VERIFIC_DIR)/%/*-linux.a,$(VERIFIC_COMPONENTS)) -lz endif +endif ifeq ($(ENABLE_PROTOBUF),1) LDLIBS += $(shell pkg-config --cflags --libs protobuf) @@ -595,7 +599,7 @@ vloghtb: $(TARGETS) $(EXTRA_TARGETS) ystests: $(TARGETS) $(EXTRA_TARGETS) rm -rf tests/ystests git clone https://github.com/YosysHQ/yosys-tests.git tests/ystests - +PATH="$$PWD:$$PATH" cd tests/ystests && $(MAKE) + +$(MAKE) PATH="$$PWD:$$PATH" -C tests/ystests @echo "" @echo " Finished \"make ystests\"." @echo "" diff --git a/backends/smt2/smt2.cc b/backends/smt2/smt2.cc index e2777ae04..418f8d766 100644 --- a/backends/smt2/smt2.cc +++ b/backends/smt2/smt2.cc @@ -554,7 +554,9 @@ struct Smt2Worker if (cell->type.in("$shift", "$shiftx")) { if (cell->getParam("\\B_SIGNED").as_bool()) { - /* FIXME */ + return export_bvop(cell, stringf("(ite (bvsge B #b%0*d) " + "(bvlshr A B) (bvlshr A (bvneg B)))", + GetSize(cell->getPort("\\B")), 0), 's'); } else { return export_bvop(cell, "(bvlshr A B)", 's'); } diff --git a/backends/smt2/smtbmc.py b/backends/smt2/smtbmc.py index 6af2a5ac1..b944ee004 100644 --- a/backends/smt2/smtbmc.py +++ b/backends/smt2/smtbmc.py @@ -1259,7 +1259,11 @@ elif covermode: smt_assert_antecedent("(|%s_t| s%d s%d)" % (topmod, i-1, i)) smt_assert_consequent(get_constr_expr(constr_assumes, i)) print_msg("Re-solving with appended steps..") - assert smt_check_sat() == "sat" + if smt_check_sat() == "unsat": + print("%s Cannot appended steps without violating assumptions!" % smt.timestamp()) + found_failed_assert = True + retstatus = False + break reached_covers = smt.bv2bin(smt.get("(covers_%d s%d)" % (coveridx, step))) assert len(reached_covers) == len(cover_desc) @@ -1377,7 +1381,11 @@ else: # not tempind, covermode smt_assert_antecedent("(|%s_h| s%d)" % (topmod, i)) smt_assert_antecedent("(|%s_t| s%d s%d)" % (topmod, i-1, i)) smt_assert_consequent(get_constr_expr(constr_assumes, i)) - assert smt_check_sat() == "sat" + print_msg("Re-solving with appended steps..") + if smt_check_sat() == "unsat": + print("%s Cannot appended steps without violating assumptions!" % smt.timestamp()) + retstatus = False + break print_anyconsts(step) for i in range(step, last_check_step+1): print_failed_asserts(i) diff --git a/backends/smt2/smtio.py b/backends/smt2/smtio.py index 3fc823e3e..68783e744 100644 --- a/backends/smt2/smtio.py +++ b/backends/smt2/smtio.py @@ -31,11 +31,19 @@ from threading import Thread # does not run out of stack frames when parsing large expressions if os.name == "posix": smtio_reclimit = 64 * 1024 - smtio_stacksize = 128 * 1024 * 1024 if sys.getrecursionlimit() < smtio_reclimit: sys.setrecursionlimit(smtio_reclimit) - if resource.getrlimit(resource.RLIMIT_STACK)[0] < smtio_stacksize: - resource.setrlimit(resource.RLIMIT_STACK, (smtio_stacksize, -1)) + + current_rlimit_stack = resource.getrlimit(resource.RLIMIT_STACK) + if current_rlimit_stack[0] != resource.RLIM_INFINITY: + smtio_stacksize = 128 * 1024 * 1024 + if os.uname().sysname == "Darwin": + # MacOS has rather conservative stack limits + smtio_stacksize = 16 * 1024 * 1024 + if current_rlimit_stack[1] != resource.RLIM_INFINITY: + smtio_stacksize = min(smtio_stacksize, current_rlimit_stack[1]) + if current_rlimit_stack[0] < smtio_stacksize: + resource.setrlimit(resource.RLIMIT_STACK, (smtio_stacksize, current_rlimit_stack[1])) # currently running solvers (so we can kill them) @@ -158,19 +166,28 @@ class SmtIo: self.unroll = False if self.solver == "yices": - self.popen_vargs = ['yices-smt2', '--incremental'] + self.solver_opts + if self.noincr: + self.popen_vargs = ['yices-smt2'] + self.solver_opts + else: + self.popen_vargs = ['yices-smt2', '--incremental'] + self.solver_opts if self.solver == "z3": self.popen_vargs = ['z3', '-smt2', '-in'] + self.solver_opts if self.solver == "cvc4": - self.popen_vargs = ['cvc4', '--incremental', '--lang', 'smt2.6' if self.logic_dt else 'smt2'] + self.solver_opts + if self.noincr: + self.popen_vargs = ['cvc4', '--lang', 'smt2.6' if self.logic_dt else 'smt2'] + self.solver_opts + else: + self.popen_vargs = ['cvc4', '--incremental', '--lang', 'smt2.6' if self.logic_dt else 'smt2'] + self.solver_opts if self.solver == "mathsat": self.popen_vargs = ['mathsat'] + self.solver_opts if self.solver == "boolector": - self.popen_vargs = ['boolector', '--smt2', '-i'] + self.solver_opts + if self.noincr: + self.popen_vargs = ['boolector', '--smt2'] + self.solver_opts + else: + self.popen_vargs = ['boolector', '--smt2', '-i'] + self.solver_opts self.unroll = True if self.solver == "abc": diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index cc275959a..2c1561552 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -172,8 +172,7 @@ bool AstNode::get_bool_attribute(RTLIL::IdString id) AstNode *attr = attributes.at(id); if (attr->type != AST_CONSTANT) - log_file_error(attr->filename, attr->linenum, "Attribute `%s' with non-constant value!\n", - id.c_str()); + log_file_error(attr->filename, attr->linenum, "Attribute `%s' with non-constant value!\n", id.c_str()); return attr->integer != 0; } @@ -969,8 +968,7 @@ static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast for (auto &attr : ast->attributes) { if (attr.second->type != AST_CONSTANT) - log_file_error(ast->filename, ast->linenum, "Attribute `%s' with non-constant value!\n", - attr.first.c_str()); + log_file_error(ast->filename, ast->linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str()); current_module->attributes[attr.first] = attr.second->asAttrConst(); } for (size_t i = 0; i < ast->children.size(); i++) { @@ -1061,8 +1059,7 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump if (design->has((*it)->str)) { RTLIL::Module *existing_mod = design->module((*it)->str); if (!nooverwrite && !overwrite && !existing_mod->get_bool_attribute("\\blackbox")) { - log_file_error((*it)->filename, (*it)->linenum, "Re-definition of module `%s'!\n", - (*it)->str.c_str()); + log_file_error((*it)->filename, (*it)->linenum, "Re-definition of module `%s'!\n", (*it)->str.c_str()); } else if (nooverwrite) { log("Ignoring re-definition of module `%s' at %s:%d.\n", (*it)->str.c_str(), (*it)->filename.c_str(), (*it)->linenum); diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index 59c309665..9531dd356 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -55,8 +55,7 @@ static RTLIL::SigSpec uniop2rtlil(AstNode *that, std::string type, int result_wi if (gen_attributes) for (auto &attr : that->attributes) { if (attr.second->type != AST_CONSTANT) - log_file_error(that->filename, that->linenum, "Attribute `%s' with non-constant value!\n", - attr.first.c_str()); + log_file_error(that->filename, that->linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str()); cell->attributes[attr.first] = attr.second->asAttrConst(); } @@ -89,8 +88,7 @@ static void widthExtend(AstNode *that, RTLIL::SigSpec &sig, int width, bool is_s if (that != NULL) for (auto &attr : that->attributes) { if (attr.second->type != AST_CONSTANT) - log_file_error(that->filename, that->linenum, "Attribute `%s' with non-constant value!\n", - attr.first.c_str()); + log_file_error(that->filename, that->linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str()); cell->attributes[attr.first] = attr.second->asAttrConst(); } @@ -117,8 +115,7 @@ static RTLIL::SigSpec binop2rtlil(AstNode *that, std::string type, int result_wi for (auto &attr : that->attributes) { if (attr.second->type != AST_CONSTANT) - log_file_error(that->filename, that->linenum, "Attribute `%s' with non-constant value!\n", - attr.first.c_str()); + log_file_error(that->filename, that->linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str()); cell->attributes[attr.first] = attr.second->asAttrConst(); } @@ -152,8 +149,7 @@ static RTLIL::SigSpec mux2rtlil(AstNode *that, const RTLIL::SigSpec &cond, const for (auto &attr : that->attributes) { if (attr.second->type != AST_CONSTANT) - log_file_error(that->filename, that->linenum, "Attribute `%s' with non-constant value!\n", - attr.first.c_str()); + log_file_error(that->filename, that->linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str()); cell->attributes[attr.first] = attr.second->asAttrConst(); } @@ -480,8 +476,7 @@ struct AST_INTERNAL::ProcessGenerator for (auto &attr : ast->attributes) { if (attr.second->type != AST_CONSTANT) - log_file_error(ast->filename, ast->linenum, "Attribute `%s' with non-constant value!\n", - attr.first.c_str()); + log_file_error(ast->filename, ast->linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str()); sw->attributes[attr.first] = attr.second->asAttrConst(); } @@ -648,8 +643,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun while (left_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { } while (right_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { } if (left_at_zero_ast->type != AST_CONSTANT || right_at_zero_ast->type != AST_CONSTANT) - log_file_error(filename, linenum, "Unsupported expression on dynamic range select on signal `%s'!\n", - str.c_str()); + log_file_error(filename, linenum, "Unsupported expression on dynamic range select on signal `%s'!\n", str.c_str()); this_width = left_at_zero_ast->integer - right_at_zero_ast->integer + 1; delete left_at_zero_ast; delete right_at_zero_ast; @@ -778,7 +772,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun while (children[0]->simplify(true, false, false, 1, -1, false, true) == true) { } if (children[0]->type != AST_CONSTANT) log_file_error(filename, linenum, "System function %s called with non-const argument!\n", - RTLIL::unescape_id(str).c_str()); + RTLIL::unescape_id(str).c_str()); width_hint = max(width_hint, int(children[0]->asInt(true))); } break; @@ -799,8 +793,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun default: for (auto f : log_files) current_ast->dumpAst(f, "verilog-ast> "); - log_file_error(filename, linenum, "Don't know how to detect sign and width for %s node!\n", - type2str(type).c_str()); + log_file_error(filename, linenum, "Don't know how to detect sign and width for %s node!\n", type2str(type).c_str()); } if (*found_real) @@ -892,11 +885,9 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) // create an RTLIL::Wire for an AST_WIRE node case AST_WIRE: { if (current_module->wires_.count(str) != 0) - log_file_error(filename, linenum, "Re-definition of signal `%s'!\n", - str.c_str()); + log_file_error(filename, linenum, "Re-definition of signal `%s'!\n", str.c_str()); if (!range_valid) - log_file_error(filename, linenum, "Signal `%s' with non-constant width!\n", - str.c_str()); + log_file_error(filename, linenum, "Signal `%s' with non-constant width!\n", str.c_str()); log_assert(range_left >= range_right || (range_left == -1 && range_right == 0)); @@ -910,8 +901,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) for (auto &attr : attributes) { if (attr.second->type != AST_CONSTANT) - log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n", - attr.first.c_str()); + log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str()); wire->attributes[attr.first] = attr.second->asAttrConst(); } } @@ -920,16 +910,14 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) // create an RTLIL::Memory for an AST_MEMORY node case AST_MEMORY: { if (current_module->memories.count(str) != 0) - log_file_error(filename, linenum, "Re-definition of memory `%s'!\n", - str.c_str()); + log_file_error(filename, linenum, "Re-definition of memory `%s'!\n", str.c_str()); log_assert(children.size() >= 2); log_assert(children[0]->type == AST_RANGE); log_assert(children[1]->type == AST_RANGE); if (!children[0]->range_valid || !children[1]->range_valid) - log_file_error(filename, linenum, "Memory `%s' with non-constant width or size!\n", - str.c_str()); + log_file_error(filename, linenum, "Memory `%s' with non-constant width or size!\n", str.c_str()); RTLIL::Memory *memory = new RTLIL::Memory; memory->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum); @@ -946,8 +934,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) for (auto &attr : attributes) { if (attr.second->type != AST_CONSTANT) - log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n", - attr.first.c_str()); + log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str()); memory->attributes[attr.first] = attr.second->asAttrConst(); } } @@ -966,8 +953,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) case AST_REALVALUE: { RTLIL::SigSpec sig = realAsConst(width_hint); - log_file_warning(filename, linenum, "converting real value %e to binary %s.\n", - realvalue, log_signal(sig)); + log_file_warning(filename, linenum, "converting real value %e to binary %s.\n", realvalue, log_signal(sig)); return sig; } @@ -994,8 +980,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) } else if (id2ast->type == AST_PARAMETER || id2ast->type == AST_LOCALPARAM) { if (id2ast->children[0]->type != AST_CONSTANT) - log_file_error(filename, linenum, "Parameter %s does not evaluate to constant value!\n", - str.c_str()); + log_file_error(filename, linenum, "Parameter %s does not evaluate to constant value!\n", str.c_str()); chunk = RTLIL::Const(id2ast->children[0]->bits); goto use_const_chunk; } @@ -1010,13 +995,11 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) is_interface = true; } else { - log_file_error(filename, linenum, "Identifier `%s' doesn't map to any signal!\n", - str.c_str()); + log_file_error(filename, linenum, "Identifier `%s' doesn't map to any signal!\n", str.c_str()); } if (id2ast->type == AST_MEMORY) - log_file_error(filename, linenum, "Identifier `%s' does map to an unexpanded memory!\n", - str.c_str()); + log_file_error(filename, linenum, "Identifier `%s' does map to an unexpanded memory!\n", str.c_str()); // If identifier is an interface, create a RTLIL::SigSpec with a dummy wire with a attribute called 'is_interface' // This makes it possible for the hierarchy pass to see what are interface connections and then replace them @@ -1051,8 +1034,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) while (left_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { } while (right_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { } if (left_at_zero_ast->type != AST_CONSTANT || right_at_zero_ast->type != AST_CONSTANT) - log_file_error(filename, linenum, "Unsupported expression on dynamic range select on signal `%s'!\n", - str.c_str()); + log_file_error(filename, linenum, "Unsupported expression on dynamic range select on signal `%s'!\n", str.c_str()); int width = left_at_zero_ast->integer - right_at_zero_ast->integer + 1; AstNode *fake_ast = new AstNode(AST_NONE, clone(), children[0]->children.size() >= 2 ? children[0]->children[1]->clone() : children[0]->children[0]->clone()); @@ -1081,7 +1063,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) if (chunk.offset >= source_width || chunk.offset + chunk.width < 0) { if (chunk.width == 1) log_file_warning(filename, linenum, "Range select out of bounds on signal `%s': Setting result bit to undef.\n", - str.c_str()); + str.c_str()); else log_file_warning(filename, linenum, "Range select [%d:%d] out of bounds on signal `%s': Setting all %d result bits to undef.\n", children[0]->range_left, children[0]->range_right, str.c_str(), chunk.width); @@ -1098,10 +1080,10 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) } if (add_undef_bits_lsb) log_file_warning(filename, linenum, "Range [%d:%d] select out of bounds on signal `%s': Setting %d LSB bits to undef.\n", - children[0]->range_left, children[0]->range_right, str.c_str(), add_undef_bits_lsb); + children[0]->range_left, children[0]->range_right, str.c_str(), add_undef_bits_lsb); if (add_undef_bits_msb) log_file_warning(filename, linenum, "Range [%d:%d] select out of bounds on signal `%s': Setting %d MSB bits to undef.\n", - children[0]->range_left, children[0]->range_right, str.c_str(), add_undef_bits_msb); + children[0]->range_left, children[0]->range_right, str.c_str(), add_undef_bits_msb); } } } @@ -1436,8 +1418,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) for (auto &attr : attributes) { if (attr.second->type != AST_CONSTANT) - log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n", - attr.first.c_str()); + log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str()); cell->attributes[attr.first] = attr.second->asAttrConst(); } @@ -1459,9 +1440,9 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) new_right.append(right[i]); } log_file_warning(filename, linenum, "Ignoring assignment to constant bits:\n" - " old assignment: %s = %s\n new assignment: %s = %s.\n", - log_signal(left), log_signal(right), - log_signal(new_left), log_signal(new_right)); + " old assignment: %s = %s\n new assignment: %s = %s.\n", + log_signal(left), log_signal(right), + log_signal(new_left), log_signal(new_right)); left = new_left; right = new_right; } @@ -1494,14 +1475,14 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) IdString paraname = child->str.empty() ? stringf("$%d", ++para_counter) : child->str; if (child->children[0]->type == AST_REALVALUE) { log_file_warning(filename, linenum, "Replacing floating point parameter %s.%s = %f with string.\n", - log_id(cell), log_id(paraname), child->children[0]->realvalue); + log_id(cell), log_id(paraname), child->children[0]->realvalue); auto strnode = AstNode::mkconst_str(stringf("%f", child->children[0]->realvalue)); strnode->cloneInto(child->children[0]); delete strnode; } if (child->children[0]->type != AST_CONSTANT) log_file_error(filename, linenum, "Parameter %s.%s with non-constant value!\n", - log_id(cell), log_id(paraname)); + log_id(cell), log_id(paraname)); cell->parameters[paraname] = child->children[0]->asParaConst(); continue; } @@ -1522,8 +1503,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) } for (auto &attr : attributes) { if (attr.second->type != AST_CONSTANT) - log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n", - attr.first.c_str()); + log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str()); cell->attributes[attr.first] = attr.second->asAttrConst(); } } @@ -1551,18 +1531,17 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) if (GetSize(children) > 1) log_file_error(filename, linenum, "System function %s got %d arguments, expected 1 or 0.\n", - RTLIL::unescape_id(str).c_str(), GetSize(children)); + RTLIL::unescape_id(str).c_str(), GetSize(children)); if (GetSize(children) == 1) { if (children[0]->type != AST_CONSTANT) log_file_error(filename, linenum, "System function %s called with non-const argument!\n", - RTLIL::unescape_id(str).c_str()); + RTLIL::unescape_id(str).c_str()); width = children[0]->asInt(true); } if (width <= 0) - log_file_error(filename, linenum, "Failed to detect width of %s!\n", - RTLIL::unescape_id(str).c_str()); + log_file_error(filename, linenum, "Failed to detect width of %s!\n", RTLIL::unescape_id(str).c_str()); Cell *cell = current_module->addCell(myid, str.substr(1)); cell->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum); @@ -1589,8 +1568,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) for (auto f : log_files) current_ast->dumpAst(f, "verilog-ast> "); type_name = type2str(type); - log_file_error(filename, linenum, "Don't know how to generate RTLIL code for %s node!\n", - type_name.c_str()); + log_file_error(filename, linenum, "Don't know how to generate RTLIL code for %s node!\n", type_name.c_str()); } return RTLIL::SigSpec(); diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index e56a62563..bb4c9735d 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -196,7 +196,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, int nargs = GetSize(children); if (nargs < 1) log_file_error(filename, linenum, "System task `%s' got %d arguments, expected >= 1.\n", - str.c_str(), int(children.size())); + str.c_str(), int(children.size())); // First argument is the format string AstNode *node_string = children[0]; @@ -240,7 +240,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, case 'X': if (next_arg >= GetSize(children)) log_file_error(filename, linenum, "Missing argument for %%%c format specifier in system task `%s'.\n", - cformat, str.c_str()); + cformat, str.c_str()); node_arg = children[next_arg++]; while (node_arg->simplify(true, false, false, stage, width_hint, sign_hint, false)) { } @@ -450,8 +450,21 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, children[0]->id2ast->is_reg = true; // if logic type is used in a block asignment if ((type == AST_ASSIGN_LE || type == AST_ASSIGN_EQ) && !children[0]->id2ast->is_reg) log_warning("wire '%s' is assigned in a block at %s:%d.\n", children[0]->str.c_str(), filename.c_str(), linenum); - if (type == AST_ASSIGN && children[0]->id2ast->is_reg) - log_warning("reg '%s' is assigned in a continuous assignment at %s:%d.\n", children[0]->str.c_str(), filename.c_str(), linenum); + if (type == AST_ASSIGN && children[0]->id2ast->is_reg) { + bool is_rand_reg = false; + if (children[1]->type == AST_FCALL) { + if (children[1]->str == "\\$anyconst") + is_rand_reg = true; + if (children[1]->str == "\\$anyseq") + is_rand_reg = true; + if (children[1]->str == "\\$allconst") + is_rand_reg = true; + if (children[1]->str == "\\$allseq") + is_rand_reg = true; + } + if (!is_rand_reg) + log_warning("reg '%s' is assigned in a continuous assignment at %s:%d.\n", children[0]->str.c_str(), filename.c_str(), linenum); + } children[0]->was_checked = true; } break; @@ -732,7 +745,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, if (current_scope.at(modname)->type != AST_CELL) log_file_error(filename, linenum, "Defparam argument `%s . %s` does not match a cell!\n", - RTLIL::unescape_id(modname).c_str(), RTLIL::unescape_id(paramname).c_str()); + RTLIL::unescape_id(modname).c_str(), RTLIL::unescape_id(paramname).c_str()); AstNode *paraset = new AstNode(AST_PARASET, children[1]->clone(), GetSize(children) > 2 ? children[2]->clone() : NULL); paraset->str = paramname; @@ -880,7 +893,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, if (children[0]->type == AST_REALVALUE) { RTLIL::Const constvalue = children[0]->realAsConst(width); log_file_warning(filename, linenum, "converting real value %e to binary %s.\n", - children[0]->realvalue, log_signal(constvalue)); + children[0]->realvalue, log_signal(constvalue)); delete children[0]; children[0] = mkconst_bits(constvalue.bits, sign_hint); did_something = true; @@ -1299,8 +1312,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, if (type == AST_PRIMITIVE) { if (children.size() < 2) - log_file_error(filename, linenum, "Insufficient number of arguments for primitive `%s'!\n", - str.c_str()); + log_file_error(filename, linenum, "Insufficient number of arguments for primitive `%s'!\n", str.c_str()); std::vector<AstNode*> children_list; for (auto child : children) { @@ -1315,8 +1327,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, if (str == "bufif0" || str == "bufif1" || str == "notif0" || str == "notif1") { if (children_list.size() != 3) - log_file_error(filename, linenum, "Invalid number of arguments for primitive `%s'!\n", - str.c_str()); + log_file_error(filename, linenum, "Invalid number of arguments for primitive `%s'!\n", str.c_str()); std::vector<RTLIL::State> z_const(1, RTLIL::State::Sz); @@ -1403,8 +1414,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, while (left_at_zero_ast->simplify(true, true, false, stage, -1, false, false)) { } while (right_at_zero_ast->simplify(true, true, false, stage, -1, false, false)) { } if (left_at_zero_ast->type != AST_CONSTANT || right_at_zero_ast->type != AST_CONSTANT) - log_file_error(filename, linenum, "Unsupported expression on dynamic range select on signal `%s'!\n", - str.c_str()); + log_file_error(filename, linenum, "Unsupported expression on dynamic range select on signal `%s'!\n", str.c_str()); result_width = abs(int(left_at_zero_ast->integer - right_at_zero_ast->integer)) + 1; } did_something = true; @@ -1775,11 +1785,11 @@ skip_dynamic_range_lvalue_expansion:; if (GetSize(children) != 1 && GetSize(children) != 2) log_file_error(filename, linenum, "System function %s got %d arguments, expected 1 or 2.\n", - RTLIL::unescape_id(str).c_str(), int(children.size())); + RTLIL::unescape_id(str).c_str(), int(children.size())); if (!current_always_clocked) log_file_error(filename, linenum, "System function %s is only allowed in clocked blocks.\n", - RTLIL::unescape_id(str).c_str()); + RTLIL::unescape_id(str).c_str()); if (GetSize(children) == 2) { @@ -1844,11 +1854,11 @@ skip_dynamic_range_lvalue_expansion:; { if (GetSize(children) != 1) log_file_error(filename, linenum, "System function %s got %d arguments, expected 1.\n", - RTLIL::unescape_id(str).c_str(), int(children.size())); + RTLIL::unescape_id(str).c_str(), int(children.size())); if (!current_always_clocked) log_file_error(filename, linenum, "System function %s is only allowed in clocked blocks.\n", - RTLIL::unescape_id(str).c_str()); + RTLIL::unescape_id(str).c_str()); AstNode *present = children.at(0)->clone(); AstNode *past = clone(); @@ -1861,10 +1871,14 @@ skip_dynamic_range_lvalue_expansion:; newNode = new AstNode(AST_NE, past, present); else if (str == "\\$rose") - newNode = new AstNode(AST_LOGIC_AND, new AstNode(AST_LOGIC_NOT, past), present); + newNode = new AstNode(AST_LOGIC_AND, + new AstNode(AST_LOGIC_NOT, new AstNode(AST_BIT_AND, past, mkconst_int(1,false))), + new AstNode(AST_BIT_AND, present, mkconst_int(1,false))); else if (str == "\\$fell") - newNode = new AstNode(AST_LOGIC_AND, past, new AstNode(AST_LOGIC_NOT, present)); + newNode = new AstNode(AST_LOGIC_AND, + new AstNode(AST_BIT_AND, past, mkconst_int(1,false)), + new AstNode(AST_LOGIC_NOT, new AstNode(AST_BIT_AND, present, mkconst_int(1,false)))); else log_abort(); @@ -1882,7 +1896,7 @@ skip_dynamic_range_lvalue_expansion:; { if (children.size() != 1) log_file_error(filename, linenum, "System function %s got %d arguments, expected 1.\n", - RTLIL::unescape_id(str).c_str(), int(children.size())); + RTLIL::unescape_id(str).c_str(), int(children.size())); AstNode *buf = children[0]->clone(); while (buf->simplify(true, false, false, stage, width_hint, sign_hint, false)) { } @@ -1907,11 +1921,11 @@ skip_dynamic_range_lvalue_expansion:; { if (str == "\\$bits" && children.size() != 1) log_file_error(filename, linenum, "System function %s got %d arguments, expected 1.\n", - RTLIL::unescape_id(str).c_str(), int(children.size())); + RTLIL::unescape_id(str).c_str(), int(children.size())); if (str == "\\$size" && children.size() != 1 && children.size() != 2) log_file_error(filename, linenum, "System function %s got %d arguments, expected 1 or 2.\n", - RTLIL::unescape_id(str).c_str(), int(children.size())); + RTLIL::unescape_id(str).c_str(), int(children.size())); int dim = 1; if (str == "\\$size" && children.size() == 2) { @@ -1985,18 +1999,18 @@ skip_dynamic_range_lvalue_expansion:; if (func_with_two_arguments) { if (children.size() != 2) log_file_error(filename, linenum, "System function %s got %d arguments, expected 2.\n", - RTLIL::unescape_id(str).c_str(), int(children.size())); + RTLIL::unescape_id(str).c_str(), int(children.size())); } else { if (children.size() != 1) log_file_error(filename, linenum, "System function %s got %d arguments, expected 1.\n", - RTLIL::unescape_id(str).c_str(), int(children.size())); + RTLIL::unescape_id(str).c_str(), int(children.size())); } if (children.size() >= 1) { while (children[0]->simplify(true, false, false, stage, width_hint, sign_hint, false)) { } if (!children[0]->isConst()) log_file_error(filename, linenum, "Failed to evaluate system function `%s' with non-constant argument.\n", - RTLIL::unescape_id(str).c_str()); + RTLIL::unescape_id(str).c_str()); int child_width_hint = width_hint; bool child_sign_hint = sign_hint; children[0]->detectSignWidth(child_width_hint, child_sign_hint); @@ -2007,7 +2021,7 @@ skip_dynamic_range_lvalue_expansion:; while (children[1]->simplify(true, false, false, stage, width_hint, sign_hint, false)) { } if (!children[1]->isConst()) log_file_error(filename, linenum, "Failed to evaluate system function `%s' with non-constant argument.\n", - RTLIL::unescape_id(str).c_str()); + RTLIL::unescape_id(str).c_str()); int child_width_hint = width_hint; bool child_sign_hint = sign_hint; children[1]->detectSignWidth(child_width_hint, child_sign_hint); @@ -2095,7 +2109,7 @@ skip_dynamic_range_lvalue_expansion:; { if (GetSize(children) < 2 || GetSize(children) > 4) log_file_error(filename, linenum, "System function %s got %d arguments, expected 2-4.\n", - RTLIL::unescape_id(str).c_str(), int(children.size())); + RTLIL::unescape_id(str).c_str(), int(children.size())); AstNode *node_filename = children[0]->clone(); while (node_filename->simplify(true, false, false, stage, width_hint, sign_hint, false)) { } @@ -3259,12 +3273,12 @@ void AstNode::replace_variables(std::map<std::string, AstNode::varinfo_t> &varia if (!children.empty()) { if (children.size() != 1 || children.at(0)->type != AST_RANGE) log_file_error(filename, linenum, "Memory access in constant function is not supported\n%s:%d: ...called from here.\n", - fcall->filename.c_str(), fcall->linenum); + fcall->filename.c_str(), fcall->linenum); children.at(0)->replace_variables(variables, fcall); while (simplify(true, false, false, 1, -1, false, true)) { } if (!children.at(0)->range_valid) log_file_error(filename, linenum, "Non-constant range\n%s:%d: ... called from here.\n", - fcall->filename.c_str(), fcall->linenum); + fcall->filename.c_str(), fcall->linenum); offset = min(children.at(0)->range_left, children.at(0)->range_right); width = min(std::abs(children.at(0)->range_left - children.at(0)->range_right) + 1, width); } @@ -3304,7 +3318,7 @@ AstNode *AstNode::eval_const_function(AstNode *fcall) while (child->simplify(true, false, false, 1, -1, false, true)) { } if (!child->range_valid) log_file_error(child->filename, child->linenum, "Can't determine size of variable %s\n%s:%d: ... called from here.\n", - child->str.c_str(), fcall->filename.c_str(), fcall->linenum); + child->str.c_str(), fcall->filename.c_str(), fcall->linenum); variables[child->str].val = RTLIL::Const(RTLIL::State::Sx, abs(child->range_left - child->range_right)+1); variables[child->str].offset = min(child->range_left, child->range_right); variables[child->str].is_signed = child->is_signed; @@ -3348,15 +3362,15 @@ AstNode *AstNode::eval_const_function(AstNode *fcall) if (stmt->children.at(1)->type != AST_CONSTANT) log_file_error(stmt->filename, stmt->linenum, "Non-constant expression in constant function\n%s:%d: ... called from here. X\n", - fcall->filename.c_str(), fcall->linenum); + fcall->filename.c_str(), fcall->linenum); if (stmt->children.at(0)->type != AST_IDENTIFIER) log_file_error(stmt->filename, stmt->linenum, "Unsupported composite left hand side in constant function\n%s:%d: ... called from here.\n", - fcall->filename.c_str(), fcall->linenum); + fcall->filename.c_str(), fcall->linenum); if (!variables.count(stmt->children.at(0)->str)) log_file_error(stmt->filename, stmt->linenum, "Assignment to non-local variable in constant function\n%s:%d: ... called from here.\n", - fcall->filename.c_str(), fcall->linenum); + fcall->filename.c_str(), fcall->linenum); if (stmt->children.at(0)->children.empty()) { variables[stmt->children.at(0)->str].val = stmt->children.at(1)->bitsAsConst(variables[stmt->children.at(0)->str].val.bits.size()); @@ -3364,7 +3378,7 @@ AstNode *AstNode::eval_const_function(AstNode *fcall) AstNode *range = stmt->children.at(0)->children.at(0); if (!range->range_valid) log_file_error(range->filename, range->linenum, "Non-constant range\n%s:%d: ... called from here.\n", - fcall->filename.c_str(), fcall->linenum); + fcall->filename.c_str(), fcall->linenum); int offset = min(range->range_left, range->range_right); int width = std::abs(range->range_left - range->range_right) + 1; varinfo_t &v = variables[stmt->children.at(0)->str]; @@ -3396,7 +3410,7 @@ AstNode *AstNode::eval_const_function(AstNode *fcall) if (cond->type != AST_CONSTANT) log_file_error(stmt->filename, stmt->linenum, "Non-constant expression in constant function\n%s:%d: ... called from here.\n", - fcall->filename.c_str(), fcall->linenum); + fcall->filename.c_str(), fcall->linenum); if (cond->asBool()) { block->children.insert(block->children.begin(), stmt->children.at(1)->clone()); @@ -3417,7 +3431,7 @@ AstNode *AstNode::eval_const_function(AstNode *fcall) if (num->type != AST_CONSTANT) log_file_error(stmt->filename, stmt->linenum, "Non-constant expression in constant function\n%s:%d: ... called from here.\n", - fcall->filename.c_str(), fcall->linenum); + fcall->filename.c_str(), fcall->linenum); block->children.erase(block->children.begin()); for (int i = 0; i < num->bitsAsConst().as_int(); i++) @@ -3455,7 +3469,7 @@ AstNode *AstNode::eval_const_function(AstNode *fcall) if (cond->type != AST_CONSTANT) log_file_error(stmt->filename, stmt->linenum, "Non-constant expression in constant function\n%s:%d: ... called from here.\n", - fcall->filename.c_str(), fcall->linenum); + fcall->filename.c_str(), fcall->linenum); found_match = cond->asBool(); delete cond; @@ -3485,7 +3499,7 @@ AstNode *AstNode::eval_const_function(AstNode *fcall) } log_file_error(stmt->filename, stmt->linenum, "Unsupported language construct in constant function\n%s:%d: ... called from here.\n", - fcall->filename.c_str(), fcall->linenum); + fcall->filename.c_str(), fcall->linenum); log_abort(); } diff --git a/frontends/liberty/liberty.cc b/frontends/liberty/liberty.cc index 66db43baf..4acfbf1cb 100644 --- a/frontends/liberty/liberty.cc +++ b/frontends/liberty/liberty.cc @@ -36,7 +36,8 @@ static RTLIL::SigSpec parse_func_identifier(RTLIL::Module *module, const char *& int id_len = 0; while (('a' <= expr[id_len] && expr[id_len] <= 'z') || ('A' <= expr[id_len] && expr[id_len] <= 'Z') || - ('0' <= expr[id_len] && expr[id_len] <= '9') || expr[id_len] == '.' || expr[id_len] == '_') id_len++; + ('0' <= expr[id_len] && expr[id_len] <= '9') || expr[id_len] == '.' || + expr[id_len] == '_' || expr[id_len] == '[' || expr[id_len] == ']') id_len++; if (id_len == 0) log_error("Expected identifier at `%s'.\n", expr); diff --git a/frontends/verific/verific.cc b/frontends/verific/verific.cc index dba3b0f0c..971f0b24a 100644 --- a/frontends/verific/verific.cc +++ b/frontends/verific/verific.cc @@ -1835,6 +1835,7 @@ struct VerificPass : public Pass { Message::RegisterCallBackMsg(msg_func); RuntimeFlags::SetVar("db_preserve_user_nets", 1); RuntimeFlags::SetVar("db_allow_external_nets", 1); + RuntimeFlags::SetVar("vhdl_support_variable_slice", 1); RuntimeFlags::SetVar("vhdl_ignore_assertion_statements", 0); RuntimeFlags::SetVar("veri_extract_dualport_rams", 0); RuntimeFlags::SetVar("veri_extract_multiport_rams", 1); diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 1fe08903c..5ab1b62df 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -125,7 +125,7 @@ static void free_attr(std::map<std::string, AstNode*> *al) %type <ast> range range_or_multirange non_opt_range non_opt_multirange range_or_signed_int %type <ast> wire_type expr basic_expr concat_list rvalue lvalue lvalue_concat_list %type <string> opt_label tok_prim_wrapper hierarchical_id -%type <boolean> opt_signed unique_case_attr +%type <boolean> opt_signed opt_property unique_case_attr %type <al> attr case_attr // operator precedence from low to high @@ -1320,7 +1320,12 @@ opt_label: }; opt_property: - TOK_PROPERTY | /* empty */; + TOK_PROPERTY { + $$ = true; + } | + /* empty */ { + $$ = false; + }; opt_stmt_label: TOK_ID ':' | /* empty */; @@ -1399,12 +1404,16 @@ assert: delete $5; else ast_stack.back()->children.push_back(new AstNode(AST_ASSUME, $5)); + if (!$3) + log_file_warning(current_filename, get_line_num(), "SystemVerilog does not allow \"restrict\" without \"property\".\n"); } | opt_stmt_label TOK_RESTRICT opt_property '(' TOK_EVENTUALLY expr ')' ';' { if (norestrict_mode) delete $6; else ast_stack.back()->children.push_back(new AstNode(AST_FAIR, $6)); + if (!$3) + log_file_warning(current_filename, get_line_num(), "SystemVerilog does not allow \"restrict\" without \"property\".\n"); }; assert_property: diff --git a/kernel/yosys.cc b/kernel/yosys.cc index 21eeadaaf..f002955ad 100644 --- a/kernel/yosys.cc +++ b/kernel/yosys.cc @@ -799,7 +799,7 @@ static void handle_label(std::string &command, bool &from_to_active, const std:: while (pos < GetSize(command) && command[pos] != ' ' && command[pos] != '\t' && command[pos] != '\r' && command[pos] != '\n') label += command[pos++]; - if (label.back() == ':' && GetSize(label) > 1) + if (GetSize(label) > 1 && label.back() == ':') { label = label.substr(0, GetSize(label)-1); command = command.substr(pos); diff --git a/passes/techmap/dfflibmap.cc b/passes/techmap/dfflibmap.cc index 416ed2bd5..b0528d473 100644 --- a/passes/techmap/dfflibmap.cc +++ b/passes/techmap/dfflibmap.cc @@ -100,6 +100,18 @@ static bool parse_pin(LibertyAst *cell, LibertyAst *attr, std::string &pin_name, for (auto child : cell->children) if (child->id == "pin" && child->args.size() == 1 && child->args[0] == pin_name) return true; + + /* If we end up here, the pin specified in the attribute does not exist, which is an error, + or, the attribute contains an expression which we do not yet support. + For now, we'll simply produce a warning to let the user know something is up. + */ + if (pin_name.find_first_of("^*|&") == std::string::npos) { + log_warning("Malformed liberty file - cannot find pin '%s' in cell '%s' - skipping.\n", pin_name.c_str(), cell->args[0].c_str()); + } + else { + log_warning("Found unsupported expression '%s' in pin attribute of cell '%s' - skipping.\n", pin_name.c_str(), cell->args[0].c_str()); + } + return false; } diff --git a/passes/techmap/libparse.cc b/passes/techmap/libparse.cc index d3b1ff02f..3927a657b 100644 --- a/passes/techmap/libparse.cc +++ b/passes/techmap/libparse.cc @@ -90,11 +90,11 @@ int LibertyParser::lexer(std::string &str) c = f.get(); } while (c == ' ' || c == '\t' || c == '\r'); - if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || ('0' <= c && c <= '9') || c == '_' || c == '-' || c == '+' || c == '.') { + if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || ('0' <= c && c <= '9') || c == '_' || c == '-' || c == '+' || c == '.' || c == '[' || c == ']') { str = c; while (1) { c = f.get(); - if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || ('0' <= c && c <= '9') || c == '_' || c == '-' || c == '+' || c == '.') + if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || ('0' <= c && c <= '9') || c == '_' || c == '-' || c == '+' || c == '.' || c == '[' || c == ']') str += c; else break; @@ -159,7 +159,7 @@ int LibertyParser::lexer(std::string &str) if (c == '\n') { line++; - return ';'; + return 'n'; } // if (c >= 32 && c < 255) @@ -175,7 +175,7 @@ LibertyAst *LibertyParser::parse() int tok = lexer(str); - while (tok == ';') + while (tok == 'n') tok = lexer(str); if (tok == '}' || tok < 0) @@ -194,6 +194,9 @@ LibertyAst *LibertyParser::parse() if (tok == ';') break; + if (tok == 'n') + continue; + if (tok == ':' && ast->value.empty()) { tok = lexer(ast->value); if (tok != 'v') @@ -249,14 +252,14 @@ LibertyAst *LibertyParser::parse() void LibertyParser::error() { - log_error("Syntax error in line %d.\n", line); + log_error("Syntax error in liberty file on line %d.\n", line); } #else void LibertyParser::error() { - fprintf(stderr, "Syntax error in line %d.\n", line); + fprintf(stderr, "Syntax error in liberty file on line %d.\n", line); exit(1); } diff --git a/techlibs/sf2/Makefile.inc b/techlibs/sf2/Makefile.inc new file mode 100644 index 000000000..cade49f37 --- /dev/null +++ b/techlibs/sf2/Makefile.inc @@ -0,0 +1,7 @@ + +OBJS += techlibs/sf2/synth_sf2.o + +$(eval $(call add_share_file,share/sf2,techlibs/sf2/arith_map.v)) +$(eval $(call add_share_file,share/sf2,techlibs/sf2/cells_map.v)) +$(eval $(call add_share_file,share/sf2,techlibs/sf2/cells_sim.v)) + diff --git a/techlibs/sf2/arith_map.v b/techlibs/sf2/arith_map.v new file mode 100644 index 000000000..462d3ce50 --- /dev/null +++ b/techlibs/sf2/arith_map.v @@ -0,0 +1,21 @@ +/* + * 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. + * + */ + + +// nothing here yet diff --git a/techlibs/sf2/cells_map.v b/techlibs/sf2/cells_map.v new file mode 100644 index 000000000..5b8888294 --- /dev/null +++ b/techlibs/sf2/cells_map.v @@ -0,0 +1,68 @@ +// module \$_DFF_N_ (input D, C, output Q); SB_DFFN _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C)); endmodule + +module \$_DFF_P_ (input D, C, output Q); + SLE _TECHMAP_REPLACE_ ( + .D(D), + .CLK(C), + .EN(1'b1), + .ALn(1'b1), + .ADn(1'b1), + .SLn(1'b1), + .SD(1'b0), + .LAT(1'b0), + .Q(Q) + ); +endmodule + +// module \$_DFFE_NN_ (input D, C, E, output Q); SB_DFFNE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(!E)); endmodule +// module \$_DFFE_PN_ (input D, C, E, output Q); SB_DFFE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(!E)); endmodule +// +// module \$_DFFE_NP_ (input D, C, E, output Q); SB_DFFNE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E)); endmodule +// module \$_DFFE_PP_ (input D, C, E, output Q); SB_DFFE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E)); endmodule +// +// module \$_DFF_NN0_ (input D, C, R, output Q); SB_DFFNR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(!R)); endmodule +// module \$_DFF_NN1_ (input D, C, R, output Q); SB_DFFNS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .S(!R)); endmodule +// module \$_DFF_PN0_ (input D, C, R, output Q); SB_DFFR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(!R)); endmodule +// module \$_DFF_PN1_ (input D, C, R, output Q); SB_DFFS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .S(!R)); endmodule +// +// module \$_DFF_NP0_ (input D, C, R, output Q); SB_DFFNR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(R)); endmodule +// module \$_DFF_NP1_ (input D, C, R, output Q); SB_DFFNS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .S(R)); endmodule +// module \$_DFF_PP0_ (input D, C, R, output Q); SB_DFFR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(R)); endmodule +// module \$_DFF_PP1_ (input D, C, R, output Q); SB_DFFS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .S(R)); endmodule +// +// module \$__DFFE_NN0 (input D, C, E, R, output Q); SB_DFFNER _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(!R)); endmodule +// module \$__DFFE_NN1 (input D, C, E, R, output Q); SB_DFFNES _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .S(!R)); endmodule +// module \$__DFFE_PN0 (input D, C, E, R, output Q); SB_DFFER _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(!R)); endmodule +// module \$__DFFE_PN1 (input D, C, E, R, output Q); SB_DFFES _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .S(!R)); endmodule +// +// module \$__DFFE_NP0 (input D, C, E, R, output Q); SB_DFFNER _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(R)); endmodule +// module \$__DFFE_NP1 (input D, C, E, R, output Q); SB_DFFNES _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .S(R)); endmodule +// module \$__DFFE_PP0 (input D, C, E, R, output Q); SB_DFFER _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(R)); endmodule +// module \$__DFFE_PP1 (input D, C, E, R, output Q); SB_DFFES _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .S(R)); endmodule + +`ifndef NO_LUT +module \$lut (A, Y); + parameter WIDTH = 0; + parameter LUT = 0; + + input [WIDTH-1:0] A; + output Y; + + generate + if (WIDTH == 1) begin + CFG1 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.Y(Y), .A(A[0])); + end else + if (WIDTH == 2) begin + CFG2 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.Y(Y), .A(A[0]), .B(A[1])); + end else + if (WIDTH == 3) begin + CFG3 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.Y(Y), .A(A[0]), .B(A[1]), .C(A[2])); + end else + if (WIDTH == 4) begin + CFG4 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.Y(Y), .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3])); + end else begin + wire _TECHMAP_FAIL_ = 1; + end + endgenerate +endmodule +`endif diff --git a/techlibs/sf2/cells_sim.v b/techlibs/sf2/cells_sim.v new file mode 100644 index 000000000..b03b2c750 --- /dev/null +++ b/techlibs/sf2/cells_sim.v @@ -0,0 +1,75 @@ +module SLE ( + output Q, + input ADn, + input ALn, + input CLK, + input D, + input LAT, + input SD, + input EN, + input SLn +); + reg q_latch, q_ff; + + always @(posedge CLK, negedge ALn) begin + if (!ALn) begin + q_ff <= !ADn; + end else if (EN) begin + if (!SLn) + q_ff <= SD; + else + q_ff <= D; + end + end + + always @* begin + if (!ALn) begin + q_latch <= !ADn; + end else if (CLK && EN) begin + if (!SLn) + q_ff <= SD; + else + q_ff <= D; + end + end + + assign Q = LAT ? q_latch : q_ff; +endmodule + +module CFG1 ( + output Y, + input A +); + parameter [1:0] INIT = 2'h0; + assign Y = INIT >> A; +endmodule + +module CFG2 ( + output Y, + input A, + input B +); + parameter [3:0] INIT = 4'h0; + assign Y = INIT >> {B, A}; +endmodule + +module CFG3 ( + output Y, + input A, + input B, + input C +); + parameter [7:0] INIT = 8'h0; + assign Y = INIT >> {C, B, A}; +endmodule + +module CFG4 ( + output Y, + input A, + input B, + input C, + input D +); + parameter [15:0] INIT = 16'h0; + assign Y = INIT >> {D, C, B, A}; +endmodule diff --git a/techlibs/sf2/synth_sf2.cc b/techlibs/sf2/synth_sf2.cc new file mode 100644 index 000000000..2676ea657 --- /dev/null +++ b/techlibs/sf2/synth_sf2.cc @@ -0,0 +1,206 @@ +/* + * 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 "kernel/register.h" +#include "kernel/celltypes.h" +#include "kernel/rtlil.h" +#include "kernel/log.h" + +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +struct SynthSf2Pass : public ScriptPass +{ + SynthSf2Pass() : ScriptPass("synth_sf2", "synthesis for SmartFusion2 and IGLOO2 FPGAs") { } + + void help() YS_OVERRIDE + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" synth_sf2 [options]\n"); + log("\n"); + log("This command runs synthesis for SmartFusion2 and IGLOO2 FPGAs.\n"); + log("\n"); + log(" -top <module>\n"); + log(" use the specified module as top module\n"); + log("\n"); + log(" -edif <file>\n"); + log(" write the design to the specified EDIF file. writing of an output file\n"); + log(" is omitted if this parameter is not specified.\n"); + log("\n"); + log(" -json <file>\n"); + log(" write the design to the specified JSON file. writing of an output file\n"); + log(" is omitted if this parameter is not specified.\n"); + log("\n"); + log(" -run <from_label>:<to_label>\n"); + log(" only run the commands between the labels (see below). an empty\n"); + log(" from label is synonymous to 'begin', and empty to label is\n"); + log(" synonymous to the end of the command list.\n"); + log("\n"); + log(" -noflatten\n"); + log(" do not flatten design before synthesis\n"); + log("\n"); + log(" -retime\n"); + log(" run 'abc' with -dff option\n"); + log("\n"); + log("\n"); + log("The following commands are executed by this synthesis command:\n"); + help_script(); + log("\n"); + } + + string top_opt, edif_file, json_file; + bool flatten, retime; + + void clear_flags() YS_OVERRIDE + { + top_opt = "-auto-top"; + edif_file = ""; + json_file = ""; + flatten = true; + retime = false; + } + + void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE + { + string run_from, run_to; + clear_flags(); + + size_t argidx; + for (argidx = 1; argidx < args.size(); argidx++) + { + if (args[argidx] == "-top" && argidx+1 < args.size()) { + top_opt = "-top " + args[++argidx]; + continue; + } + if (args[argidx] == "-edif" && argidx+1 < args.size()) { + edif_file = args[++argidx]; + continue; + } + if (args[argidx] == "-json" && argidx+1 < args.size()) { + json_file = args[++argidx]; + continue; + } + if (args[argidx] == "-run" && argidx+1 < args.size()) { + size_t pos = args[argidx+1].find(':'); + if (pos == std::string::npos) + break; + run_from = args[++argidx].substr(0, pos); + run_to = args[argidx].substr(pos+1); + continue; + } + if (args[argidx] == "-noflatten") { + flatten = false; + continue; + } + if (args[argidx] == "-retime") { + retime = true; + continue; + } + break; + } + extra_args(args, argidx, design); + + if (!design->full_selection()) + log_cmd_error("This comannd only operates on fully selected designs!\n"); + + log_header(design, "Executing SYNTH_SF2 pass.\n"); + log_push(); + + run_script(design, run_from, run_to); + + log_pop(); + } + + void script() YS_OVERRIDE + { + if (check_label("begin")) + { + run("read_verilog -lib +/sf2/cells_sim.v"); + run(stringf("hierarchy -check %s", help_mode ? "-top <top>" : top_opt.c_str())); + } + + if (flatten && check_label("flatten", "(unless -noflatten)")) + { + run("proc"); + run("flatten"); + run("tribuf -logic"); + run("deminout"); + } + + if (check_label("coarse")) + { + run("synth -run coarse"); + } + + if (check_label("fine")) + { + run("opt -fast -mux_undef -undriven -fine"); + run("memory_map"); + run("opt -undriven -fine"); + run("techmap -map +/techmap.v -map +/sf2/arith_map.v"); + if (retime || help_mode) + run("abc -dff", "(only if -retime)"); + } + + if (check_label("map_ffs")) + { + run("dffsr2dff"); + run("techmap -D NO_LUT -map +/sf2/cells_map.v"); + run("opt_expr -mux_undef"); + run("simplemap"); + // run("sf2_ffinit"); + // run("sf2_ffssr"); + // run("sf2_opt -full"); + } + + if (check_label("map_luts")) + { + run("abc -lut 4"); + run("clean"); + } + + if (check_label("map_cells")) + { + run("techmap -map +/sf2/cells_map.v"); + run("clean"); + } + + if (check_label("check")) + { + run("hierarchy -check"); + run("stat"); + run("check -noinit"); + } + + if (check_label("edif")) + { + if (!edif_file.empty() || help_mode) + run(stringf("write_edif %s", help_mode ? "<file-name>" : edif_file.c_str())); + } + + if (check_label("json")) + { + if (!json_file.empty() || help_mode) + run(stringf("write_json %s", help_mode ? "<file-name>" : json_file.c_str())); + } + } +} SynthSf2Pass; + +PRIVATE_NAMESPACE_END |