mirror of https://github.com/YosysHQ/yosys.git
Merge branch 'master' of github.com:YosysHQ/yosys
This commit is contained in:
commit
f86d153cef
8
Makefile
8
Makefile
|
@ -294,7 +294,7 @@ endif
|
|||
PY_WRAPPER_FILE = kernel/python_wrappers
|
||||
OBJS += $(PY_WRAPPER_FILE).o
|
||||
PY_GEN_SCRIPT= py_wrap_generator
|
||||
PY_WRAP_INCLUDES := $(shell python$(PYTHON_VERSION) -c "import $(PY_GEN_SCRIPT); $(PY_GEN_SCRIPT).print_includes()")
|
||||
PY_WRAP_INCLUDES := $(shell python$(PYTHON_VERSION) -c "from misc import $(PY_GEN_SCRIPT); $(PY_GEN_SCRIPT).print_includes()")
|
||||
endif
|
||||
|
||||
ifeq ($(ENABLE_READLINE),1)
|
||||
|
@ -550,9 +550,9 @@ libyosys.so: $(filter-out kernel/driver.o,$(OBJS))
|
|||
$(Q) mkdir -p $(dir $@)
|
||||
$(P) cat $< | grep -E -v "#[ ]*(include|error)" | $(LD) -x c++ -o $@ -E -P -
|
||||
|
||||
$(PY_WRAPPER_FILE).cc: $(PY_GEN_SCRIPT).py $(PY_WRAP_INCLUDES)
|
||||
$(PY_WRAPPER_FILE).cc: misc/$(PY_GEN_SCRIPT).py $(PY_WRAP_INCLUDES)
|
||||
$(Q) mkdir -p $(dir $@)
|
||||
$(P) python$(PYTHON_VERSION) -c "import $(PY_GEN_SCRIPT); $(PY_GEN_SCRIPT).gen_wrappers(\"$(PY_WRAPPER_FILE).cc\")"
|
||||
$(P) python$(PYTHON_VERSION) -c "from misc import $(PY_GEN_SCRIPT); $(PY_GEN_SCRIPT).gen_wrappers(\"$(PY_WRAPPER_FILE).cc\")"
|
||||
|
||||
%.o: %.cpp
|
||||
$(Q) mkdir -p $(dir $@)
|
||||
|
@ -685,7 +685,7 @@ ifeq ($(ENABLE_LIBYOSYS),1)
|
|||
ifeq ($(ENABLE_PYOSYS),1)
|
||||
$(INSTALL_SUDO) mkdir -p $(PYTHON_DESTDIR)/pyosys
|
||||
$(INSTALL_SUDO) cp libyosys.so $(PYTHON_DESTDIR)/pyosys
|
||||
$(INSTALL_SUDO) cp __init__.py $(PYTHON_DESTDIR)/pyosys
|
||||
$(INSTALL_SUDO) cp misc/__init__.py $(PYTHON_DESTDIR)/pyosys
|
||||
endif
|
||||
endif
|
||||
|
||||
|
|
|
@ -164,6 +164,7 @@ struct FirrtlWorker
|
|||
};
|
||||
/* Memories defined within this module. */
|
||||
struct memory {
|
||||
Cell *pCell; // for error reporting
|
||||
string name; // memory name
|
||||
int abits; // number of address bits
|
||||
int size; // size (in units) of the memory
|
||||
|
@ -174,8 +175,37 @@ struct FirrtlWorker
|
|||
vector<write_port> write_ports;
|
||||
std::string init_file;
|
||||
std::string init_file_srcFileSpec;
|
||||
memory(string name, int abits, int size, int width) : name(name), abits(abits), size(size), width(width), read_latency(0), write_latency(1), init_file(""), init_file_srcFileSpec("") {}
|
||||
memory() : read_latency(0), write_latency(1), init_file(""), init_file_srcFileSpec(""){}
|
||||
string srcLine;
|
||||
memory(Cell *pCell, string name, int abits, int size, int width) : pCell(pCell), name(name), abits(abits), size(size), width(width), read_latency(0), write_latency(1), init_file(""), init_file_srcFileSpec("") {
|
||||
// Provide defaults for abits or size if one (but not the other) is specified.
|
||||
if (this->abits == 0 && this->size != 0) {
|
||||
this->abits = ceil_log2(this->size);
|
||||
} else if (this->abits != 0 && this->size == 0) {
|
||||
this->size = 1 << this->abits;
|
||||
}
|
||||
// Sanity-check this construction.
|
||||
if (this->name == "") {
|
||||
log_error("Nameless memory%s\n", this->atLine());
|
||||
}
|
||||
if (this->abits == 0 && this->size == 0) {
|
||||
log_error("Memory %s has zero address bits and size%s\n", this->name.c_str(), this->atLine());
|
||||
}
|
||||
if (this->width == 0) {
|
||||
log_error("Memory %s has zero width%s\n", this->name.c_str(), this->atLine());
|
||||
}
|
||||
}
|
||||
// We need a default constructor for the dict insert.
|
||||
memory() : pCell(0), read_latency(0), write_latency(1), init_file(""), init_file_srcFileSpec(""){}
|
||||
|
||||
const char *atLine() {
|
||||
if (srcLine == "") {
|
||||
if (pCell) {
|
||||
auto p = pCell->attributes.find("\\src");
|
||||
srcLine = " at " + p->second.decode_string();
|
||||
}
|
||||
}
|
||||
return srcLine.c_str();
|
||||
}
|
||||
void add_memory_read_port(read_port &rp) {
|
||||
read_ports.push_back(rp);
|
||||
}
|
||||
|
@ -604,7 +634,7 @@ struct FirrtlWorker
|
|||
int abits = cell->parameters.at("\\ABITS").as_int();
|
||||
int width = cell->parameters.at("\\WIDTH").as_int();
|
||||
int size = cell->parameters.at("\\SIZE").as_int();
|
||||
memory m(mem_id, abits, size, width);
|
||||
memory m(cell, mem_id, abits, size, width);
|
||||
int rd_ports = cell->parameters.at("\\RD_PORTS").as_int();
|
||||
int wr_ports = cell->parameters.at("\\WR_PORTS").as_int();
|
||||
|
||||
|
@ -681,6 +711,8 @@ struct FirrtlWorker
|
|||
{
|
||||
std::string cell_type = fid(cell->type);
|
||||
std::string mem_id = make_id(cell->parameters["\\MEMID"].decode_string());
|
||||
int abits = cell->parameters.at("\\ABITS").as_int();
|
||||
int width = cell->parameters.at("\\WIDTH").as_int();
|
||||
memory *mp = nullptr;
|
||||
if (cell->type == "$meminit" ) {
|
||||
log_error("$meminit (%s.%s.%s) currently unsupported\n", log_id(module), log_id(cell), mem_id.c_str());
|
||||
|
@ -693,6 +725,11 @@ struct FirrtlWorker
|
|||
Const clk_enable = cell->parameters.at("\\CLK_ENABLE");
|
||||
Const clk_polarity = cell->parameters.at("\\CLK_POLARITY");
|
||||
|
||||
// Do we already have an entry for this memory?
|
||||
if (memories.count(mem_id) == 0) {
|
||||
memory m(cell, mem_id, abits, 0, width);
|
||||
register_memory(m);
|
||||
}
|
||||
mp = &memories.at(mem_id);
|
||||
int portNum = 0;
|
||||
bool transparency = false;
|
||||
|
@ -890,7 +927,7 @@ struct FirrtlWorker
|
|||
|
||||
// If we have any memory definitions, output them.
|
||||
for (auto kv : memories) {
|
||||
memory m = kv.second;
|
||||
memory &m = kv.second;
|
||||
f << stringf(" mem %s:\n", m.name.c_str());
|
||||
f << stringf(" data-type => UInt<%d>\n", m.width);
|
||||
f << stringf(" depth => %d\n", m.size);
|
||||
|
|
|
@ -1172,6 +1172,15 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
|
|||
varbuf->children[0] = buf;
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (type == AST_FOR) {
|
||||
AstNode *buf = next_ast->clone();
|
||||
delete buf->children[1];
|
||||
buf->children[1] = varbuf->children[0]->clone();
|
||||
current_block->children.insert(current_block->children.begin() + current_block_idx++, buf);
|
||||
}
|
||||
#endif
|
||||
|
||||
current_scope[varbuf->str] = backup_scope_varbuf;
|
||||
delete varbuf;
|
||||
delete_children();
|
||||
|
|
|
@ -242,8 +242,6 @@ struct VerilogFrontend : public Frontend {
|
|||
nowb_mode = false;
|
||||
default_nettype_wire = true;
|
||||
|
||||
log_header(design, "Executing Verilog-2005 frontend.\n");
|
||||
|
||||
args.insert(args.begin()+1, verilog_defaults.begin(), verilog_defaults.end());
|
||||
|
||||
size_t argidx;
|
||||
|
@ -415,6 +413,8 @@ struct VerilogFrontend : public Frontend {
|
|||
}
|
||||
extra_args(f, filename, args, argidx);
|
||||
|
||||
log_header(design, "Executing Verilog-2005 frontend: %s\n", filename.c_str());
|
||||
|
||||
log("Parsing %s%s input from `%s' to AST representation.\n",
|
||||
formal_mode ? "formal " : "", sv_mode ? "SystemVerilog" : "Verilog", filename.c_str());
|
||||
|
||||
|
|
|
@ -529,13 +529,13 @@ int main(int argc, char **argv)
|
|||
log_error("Can't open dependencies file for writing: %s\n", strerror(errno));
|
||||
bool first = true;
|
||||
for (auto fn : yosys_output_files) {
|
||||
fprintf(f, "%s%s", first ? "" : " ", fn.c_str());
|
||||
fprintf(f, "%s%s", first ? "" : " ", escape_filename_spaces(fn).c_str());
|
||||
first = false;
|
||||
}
|
||||
fprintf(f, ":");
|
||||
for (auto fn : yosys_input_files) {
|
||||
if (yosys_output_files.count(fn) == 0)
|
||||
fprintf(f, " %s", fn.c_str());
|
||||
fprintf(f, " %s", escape_filename_spaces(fn).c_str());
|
||||
}
|
||||
fprintf(f, "\n");
|
||||
}
|
||||
|
|
|
@ -3456,7 +3456,7 @@ bool RTLIL::SigSpec::operator ==(const RTLIL::SigSpec &other) const
|
|||
pack();
|
||||
other.pack();
|
||||
|
||||
if (chunks_.size() != chunks_.size())
|
||||
if (chunks_.size() != other.chunks_.size())
|
||||
return false;
|
||||
|
||||
updhash();
|
||||
|
|
|
@ -482,6 +482,20 @@ void remove_directory(std::string dirname)
|
|||
#endif
|
||||
}
|
||||
|
||||
std::string escape_filename_spaces(const std::string& filename)
|
||||
{
|
||||
std::string out;
|
||||
out.reserve(filename.size());
|
||||
for (auto c : filename)
|
||||
{
|
||||
if (c == ' ')
|
||||
out += "\\ ";
|
||||
else
|
||||
out.push_back(c);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
int GetSize(RTLIL::Wire *wire)
|
||||
{
|
||||
return wire->width;
|
||||
|
|
|
@ -257,6 +257,7 @@ std::string make_temp_dir(std::string template_str = "/tmp/yosys_XXXXXX");
|
|||
bool check_file_exists(std::string filename, bool is_exec = false);
|
||||
bool is_absolute_path(std::string filename);
|
||||
void remove_directory(std::string dirname);
|
||||
std::string escape_filename_spaces(const std::string& filename);
|
||||
|
||||
template<typename T> int GetSize(const T &obj) { return obj.size(); }
|
||||
int GetSize(RTLIL::Wire *wire);
|
||||
|
|
|
@ -291,7 +291,7 @@ struct QwpWorker
|
|||
// gaussian elimination
|
||||
for (int i = 0; i < N; i++)
|
||||
{
|
||||
if (config.verbose && ((i+1) % (N/15)) == 0)
|
||||
if (config.verbose && N > 15 && ((i+1) % (N/15)) == 0)
|
||||
log("> Solved %d%%: %d/%d\n", (100*(i+1))/N, i+1, N);
|
||||
|
||||
// find best row
|
||||
|
|
|
@ -44,7 +44,10 @@ struct EquivOptPass:public ScriptPass
|
|||
log(" useful for handling architecture-specific primitives.\n");
|
||||
log("\n");
|
||||
log(" -assert\n");
|
||||
log(" produce an error if the circuits are not equivalent\n");
|
||||
log(" produce an error if the circuits are not equivalent.\n");
|
||||
log("\n");
|
||||
log(" -undef\n");
|
||||
log(" enable modelling of undef states during equiv_induct.\n");
|
||||
log("\n");
|
||||
log("The following commands are executed by this verification command:\n");
|
||||
help_script();
|
||||
|
@ -52,13 +55,14 @@ struct EquivOptPass:public ScriptPass
|
|||
}
|
||||
|
||||
std::string command, techmap_opts;
|
||||
bool assert;
|
||||
bool assert, undef;
|
||||
|
||||
void clear_flags() YS_OVERRIDE
|
||||
{
|
||||
command = "";
|
||||
techmap_opts = "";
|
||||
assert = false;
|
||||
undef = false;
|
||||
}
|
||||
|
||||
void execute(std::vector < std::string > args, RTLIL::Design * design) YS_OVERRIDE
|
||||
|
@ -84,6 +88,10 @@ struct EquivOptPass:public ScriptPass
|
|||
assert = true;
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-undef") {
|
||||
undef = true;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -139,7 +147,12 @@ struct EquivOptPass:public ScriptPass
|
|||
|
||||
if (check_label("prove")) {
|
||||
run("equiv_make gold gate equiv");
|
||||
run("equiv_induct equiv");
|
||||
if (help_mode)
|
||||
run("equiv_induct [-undef] equiv");
|
||||
else if (undef)
|
||||
run("equiv_induct -undef equiv");
|
||||
else
|
||||
run("equiv_induct equiv");
|
||||
if (help_mode)
|
||||
run("equiv_status [-assert] equiv");
|
||||
else if (assert)
|
||||
|
|
|
@ -281,13 +281,26 @@ void rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos
|
|||
maybe_del_wires.push_back(wire);
|
||||
} else {
|
||||
log_assert(GetSize(s1) == GetSize(s2));
|
||||
Const initval;
|
||||
if (wire->attributes.count("\\init"))
|
||||
initval = wire->attributes.at("\\init");
|
||||
if (GetSize(initval) != GetSize(wire))
|
||||
initval.bits.resize(GetSize(wire), State::Sx);
|
||||
RTLIL::SigSig new_conn;
|
||||
for (int i = 0; i < GetSize(s1); i++)
|
||||
if (s1[i] != s2[i]) {
|
||||
if (s2[i] == State::Sx && (initval[i] == State::S0 || initval[i] == State::S1)) {
|
||||
s2[i] = initval[i];
|
||||
initval[i] = State::Sx;
|
||||
}
|
||||
new_conn.first.append_bit(s1[i]);
|
||||
new_conn.second.append_bit(s2[i]);
|
||||
}
|
||||
if (new_conn.first.size() > 0) {
|
||||
if (initval.is_fully_undef())
|
||||
wire->attributes.erase("\\init");
|
||||
else
|
||||
wire->attributes.at("\\init") = initval;
|
||||
used_signals.add(new_conn.first);
|
||||
used_signals.add(new_conn.second);
|
||||
module->connect(new_conn);
|
||||
|
|
|
@ -39,6 +39,9 @@ void replace_undriven(RTLIL::Design *design, RTLIL::Module *module)
|
|||
SigPool used_signals;
|
||||
SigPool all_signals;
|
||||
|
||||
dict<SigBit, pair<Wire*, State>> initbits;
|
||||
pool<Wire*> revisit_initwires;
|
||||
|
||||
for (auto cell : module->cells())
|
||||
for (auto &conn : cell->connections()) {
|
||||
if (!ct.cell_known(cell->type) || ct.cell_output(cell->type, conn.first))
|
||||
|
@ -48,6 +51,14 @@ void replace_undriven(RTLIL::Design *design, RTLIL::Module *module)
|
|||
}
|
||||
|
||||
for (auto wire : module->wires()) {
|
||||
if (wire->attributes.count("\\init")) {
|
||||
SigSpec sig = sigmap(wire);
|
||||
Const initval = wire->attributes.at("\\init");
|
||||
for (int i = 0; i < GetSize(initval) && i < GetSize(wire); i++) {
|
||||
if (initval[i] == State::S0 || initval[i] == State::S1)
|
||||
initbits[sig[i]] = make_pair(wire, initval[i]);
|
||||
}
|
||||
}
|
||||
if (wire->port_input)
|
||||
driven_signals.add(sigmap(wire));
|
||||
if (wire->port_output)
|
||||
|
@ -67,10 +78,38 @@ void replace_undriven(RTLIL::Design *design, RTLIL::Module *module)
|
|||
if (sig.size() == 0)
|
||||
continue;
|
||||
|
||||
log_debug("Setting undriven signal in %s to undef: %s\n", RTLIL::id2cstr(module->name), log_signal(c));
|
||||
module->connect(RTLIL::SigSig(c, RTLIL::SigSpec(RTLIL::State::Sx, c.width)));
|
||||
Const val(RTLIL::State::Sx, GetSize(sig));
|
||||
for (int i = 0; i < GetSize(sig); i++) {
|
||||
SigBit bit = sigmap(sig[i]);
|
||||
auto cursor = initbits.find(bit);
|
||||
if (cursor != initbits.end()) {
|
||||
revisit_initwires.insert(cursor->second.first);
|
||||
val[i] = cursor->second.second;
|
||||
}
|
||||
}
|
||||
|
||||
log_debug("Setting undriven signal in %s to constant: %s = %s\n", RTLIL::id2cstr(module->name), log_signal(sig), log_signal(val));
|
||||
module->connect(sig, val);
|
||||
did_something = true;
|
||||
}
|
||||
|
||||
if (!revisit_initwires.empty())
|
||||
{
|
||||
SigMap sm2(module);
|
||||
|
||||
for (auto wire : revisit_initwires) {
|
||||
SigSpec sig = sm2(wire);
|
||||
Const initval = wire->attributes.at("\\init");
|
||||
for (int i = 0; i < GetSize(initval) && i < GetSize(wire); i++) {
|
||||
if (SigBit(initval[i]) == sig[i])
|
||||
initval[i] = State::Sx;
|
||||
}
|
||||
if (initval.is_fully_undef())
|
||||
wire->attributes.erase("\\init");
|
||||
else
|
||||
wire->attributes["\\init"] = initval;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void replace_cell(SigMap &assign_map, RTLIL::Module *module, RTLIL::Cell *cell, std::string info, std::string out_port, RTLIL::SigSpec out_val)
|
||||
|
|
|
@ -180,6 +180,8 @@ struct WreduceWorker
|
|||
}
|
||||
|
||||
auto info = mi.query(sig_q[i]);
|
||||
if (info == nullptr)
|
||||
return;
|
||||
if (!info->is_output && GetSize(info->ports) == 1 && !keep_bits.count(mi.sigmap(sig_q[i]))) {
|
||||
remove_init_bits.insert(sig_q[i]);
|
||||
sig_d.remove(i);
|
||||
|
|
|
@ -1169,6 +1169,7 @@ struct SatPass : public Pass {
|
|||
if (args[argidx] == "-tempinduct-def") {
|
||||
tempinduct = true;
|
||||
tempinduct_def = true;
|
||||
enable_undef = true;
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-tempinduct-baseonly") {
|
||||
|
|
|
@ -253,7 +253,7 @@ struct SynthEcp5Pass : public ScriptPass
|
|||
if (!nodffe)
|
||||
run("dff2dffe -direct-match $_DFF_* -direct-match $__DFFS_*");
|
||||
run("techmap -D NO_LUT -map +/ecp5/cells_map.v");
|
||||
run("opt_expr -mux_undef");
|
||||
run("opt_expr -undriven -mux_undef");
|
||||
run("simplemap");
|
||||
run("ecp5_ffinit");
|
||||
}
|
||||
|
|
|
@ -225,11 +225,13 @@ struct SynthIce40Pass : public ScriptPass
|
|||
run("proc");
|
||||
}
|
||||
|
||||
if (flatten && check_label("flatten", "(unless -noflatten)"))
|
||||
if (check_label("flatten", "(unless -noflatten)"))
|
||||
{
|
||||
run("flatten");
|
||||
run("tribuf -logic");
|
||||
run("deminout");
|
||||
if (flatten) {
|
||||
run("flatten");
|
||||
run("tribuf -logic");
|
||||
run("deminout");
|
||||
}
|
||||
}
|
||||
|
||||
if (check_label("coarse"))
|
||||
|
|
|
@ -25,18 +25,9 @@
|
|||
USING_YOSYS_NAMESPACE
|
||||
PRIVATE_NAMESPACE_BEGIN
|
||||
|
||||
bool check_label(bool &active, std::string run_from, std::string run_to, std::string label)
|
||||
struct SynthXilinxPass : public ScriptPass
|
||||
{
|
||||
if (label == run_from)
|
||||
active = true;
|
||||
if (label == run_to)
|
||||
active = false;
|
||||
return active;
|
||||
}
|
||||
|
||||
struct SynthXilinxPass : public Pass
|
||||
{
|
||||
SynthXilinxPass() : Pass("synth_xilinx", "synthesis for Xilinx FPGAs") { }
|
||||
SynthXilinxPass() : ScriptPass("synth_xilinx", "synthesis for Xilinx FPGAs") { }
|
||||
|
||||
void help() YS_OVERRIDE
|
||||
{
|
||||
|
@ -85,79 +76,30 @@ struct SynthXilinxPass : public Pass
|
|||
log("\n");
|
||||
log("\n");
|
||||
log("The following commands are executed by this synthesis command:\n");
|
||||
log("\n");
|
||||
log(" begin:\n");
|
||||
log(" read_verilog -lib +/xilinx/cells_sim.v\n");
|
||||
log(" read_verilog -lib +/xilinx/cells_xtra.v\n");
|
||||
log(" read_verilog -lib +/xilinx/brams_bb.v\n");
|
||||
log(" hierarchy -check -top <top>\n");
|
||||
log("\n");
|
||||
log(" flatten: (only if -flatten)\n");
|
||||
log(" proc\n");
|
||||
log(" flatten\n");
|
||||
log("\n");
|
||||
log(" coarse:\n");
|
||||
log(" synth -run coarse\n");
|
||||
log("\n");
|
||||
log(" bram: (only executed when '-nobram' is not given)\n");
|
||||
log(" memory_bram -rules +/xilinx/brams.txt\n");
|
||||
log(" techmap -map +/xilinx/brams_map.v\n");
|
||||
log("\n");
|
||||
log(" dram: (only executed when '-nodram' is not given)\n");
|
||||
log(" memory_bram -rules +/xilinx/drams.txt\n");
|
||||
log(" techmap -map +/xilinx/drams_map.v\n");
|
||||
log("\n");
|
||||
log(" fine:\n");
|
||||
log(" opt -fast\n");
|
||||
log(" memory_map\n");
|
||||
log(" dffsr2dff\n");
|
||||
log(" dff2dffe\n");
|
||||
log(" techmap -map +/xilinx/arith_map.v\n");
|
||||
log(" opt -fast\n");
|
||||
log("\n");
|
||||
log(" map_cells:\n");
|
||||
log(" simplemap t:$dff t:$dffe (without '-nosrl' only)\n");
|
||||
log(" pmux2shiftx (without '-nosrl' only)\n");
|
||||
log(" opt_expr -mux_undef (without '-nosrl' only)\n");
|
||||
log(" shregmap -tech xilinx -minlen 3 (without '-nosrl' only)\n");
|
||||
log(" techmap -map +/xilinx/cells_map.v\n");
|
||||
log(" clean\n");
|
||||
log("\n");
|
||||
log(" map_luts:\n");
|
||||
log(" opt -full\n");
|
||||
log(" techmap -map +/techmap.v -D _NO_POS_SR -map +/xilinx/ff_map.v\n");
|
||||
log(" abc -luts 2:2,3,6:5,10,20 [-dff]\n");
|
||||
log(" clean\n");
|
||||
log(" shregmap -minlen 3 -init -params -enpol any_or_none (without '-nosrl' only)\n");
|
||||
log(" techmap -map +/xilinx/lut_map.v -map +/xilinx/ff_map.v -map +/xilinx/cells_map.v");
|
||||
log(" dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT -ff FDSE Q INIT \\\n");
|
||||
log(" -ff FDRE_1 Q INIT -ff FDCE_1 Q INIT -ff FDPE_1 Q INIT -ff FDSE_1 Q INIT\n");
|
||||
log(" clean\n");
|
||||
log("\n");
|
||||
log(" check:\n");
|
||||
log(" hierarchy -check\n");
|
||||
log(" stat\n");
|
||||
log(" check -noinit\n");
|
||||
log("\n");
|
||||
log(" edif: (only if -edif)\n");
|
||||
log(" write_edif <file-name>\n");
|
||||
log("\n");
|
||||
log(" blif: (only if -blif)\n");
|
||||
log(" write_blif <file-name>\n");
|
||||
help_script();
|
||||
log("\n");
|
||||
}
|
||||
|
||||
std::string top_opt, edif_file, blif_file;
|
||||
bool flatten, retime, vpr, nobram, nodram, nosrl;
|
||||
|
||||
void clear_flags() YS_OVERRIDE
|
||||
{
|
||||
top_opt = "-auto-top";
|
||||
edif_file.clear();
|
||||
blif_file.clear();
|
||||
flatten = false;
|
||||
retime = false;
|
||||
vpr = false;
|
||||
nobram = false;
|
||||
nodram = false;
|
||||
nosrl = false;
|
||||
}
|
||||
|
||||
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
|
||||
{
|
||||
std::string top_opt = "-auto-top";
|
||||
std::string edif_file;
|
||||
std::string blif_file;
|
||||
std::string run_from, run_to;
|
||||
bool flatten = false;
|
||||
bool retime = false;
|
||||
bool vpr = false;
|
||||
bool nobram = false;
|
||||
bool nodram = false;
|
||||
bool nosrl = false;
|
||||
clear_flags();
|
||||
|
||||
size_t argidx;
|
||||
for (argidx = 1; argidx < args.size(); argidx++)
|
||||
|
@ -213,127 +155,128 @@ struct SynthXilinxPass : public Pass
|
|||
if (!design->full_selection())
|
||||
log_cmd_error("This command only operates on fully selected designs!\n");
|
||||
|
||||
bool active = run_from.empty();
|
||||
|
||||
log_header(design, "Executing SYNTH_XILINX pass.\n");
|
||||
log_push();
|
||||
|
||||
if (check_label(active, run_from, run_to, "begin"))
|
||||
{
|
||||
if (vpr) {
|
||||
Pass::call(design, "read_verilog -lib -D_EXPLICIT_CARRY +/xilinx/cells_sim.v");
|
||||
} else {
|
||||
Pass::call(design, "read_verilog -lib +/xilinx/cells_sim.v");
|
||||
}
|
||||
run_script(design, run_from, run_to);
|
||||
|
||||
Pass::call(design, "read_verilog -lib +/xilinx/cells_xtra.v");
|
||||
log_pop();
|
||||
}
|
||||
|
||||
if (!nobram) {
|
||||
Pass::call(design, "read_verilog -lib +/xilinx/brams_bb.v");
|
||||
}
|
||||
void script() YS_OVERRIDE
|
||||
{
|
||||
if (check_label("begin")) {
|
||||
if (vpr)
|
||||
run("read_verilog -lib -D_EXPLICIT_CARRY +/xilinx/cells_sim.v");
|
||||
else
|
||||
run("read_verilog -lib +/xilinx/cells_sim.v");
|
||||
|
||||
Pass::call(design, stringf("hierarchy -check %s", top_opt.c_str()));
|
||||
run("read_verilog -lib +/xilinx/cells_xtra.v");
|
||||
|
||||
if (!nobram || help_mode)
|
||||
run("read_verilog -lib +/xilinx/brams_bb.v", "(skip if '-nobram')");
|
||||
|
||||
run(stringf("hierarchy -check %s", top_opt.c_str()));
|
||||
}
|
||||
|
||||
if (flatten && check_label(active, run_from, run_to, "flatten"))
|
||||
{
|
||||
Pass::call(design, "proc");
|
||||
Pass::call(design, "flatten");
|
||||
}
|
||||
|
||||
if (check_label(active, run_from, run_to, "coarse"))
|
||||
{
|
||||
Pass::call(design, "synth -run coarse");
|
||||
}
|
||||
|
||||
if (check_label(active, run_from, run_to, "bram"))
|
||||
{
|
||||
if (!nobram) {
|
||||
Pass::call(design, "memory_bram -rules +/xilinx/brams.txt");
|
||||
Pass::call(design, "techmap -map +/xilinx/brams_map.v");
|
||||
if (check_label("flatten", "(with '-flatten' only)")) {
|
||||
if (flatten || help_mode) {
|
||||
run("proc");
|
||||
run("flatten");
|
||||
}
|
||||
}
|
||||
|
||||
if (check_label(active, run_from, run_to, "dram"))
|
||||
{
|
||||
if (!nodram) {
|
||||
Pass::call(design, "memory_bram -rules +/xilinx/drams.txt");
|
||||
Pass::call(design, "techmap -map +/xilinx/drams_map.v");
|
||||
if (check_label("coarse")) {
|
||||
run("synth -run coarse");
|
||||
}
|
||||
|
||||
if (check_label("bram", "(skip if '-nobram')")) {
|
||||
if (!nobram || help_mode) {
|
||||
run("memory_bram -rules +/xilinx/brams.txt");
|
||||
run("techmap -map +/xilinx/brams_map.v");
|
||||
}
|
||||
}
|
||||
|
||||
if (check_label(active, run_from, run_to, "fine"))
|
||||
{
|
||||
Pass::call(design, "opt -fast");
|
||||
Pass::call(design, "memory_map");
|
||||
Pass::call(design, "dffsr2dff");
|
||||
Pass::call(design, "dff2dffe");
|
||||
|
||||
if (vpr) {
|
||||
Pass::call(design, "techmap -map +/xilinx/arith_map.v -D _EXPLICIT_CARRY");
|
||||
} else {
|
||||
Pass::call(design, "techmap -map +/xilinx/arith_map.v");
|
||||
if (check_label("dram", "(skip if '-nodram')")) {
|
||||
if (!nodram || help_mode) {
|
||||
run("memory_bram -rules +/xilinx/drams.txt");
|
||||
run("techmap -map +/xilinx/drams_map.v");
|
||||
}
|
||||
|
||||
Pass::call(design, "opt -fast");
|
||||
}
|
||||
|
||||
if (check_label(active, run_from, run_to, "map_cells"))
|
||||
if (check_label("fine")) {
|
||||
run("opt -fast");
|
||||
run("memory_map");
|
||||
run("dffsr2dff");
|
||||
run("dff2dffe");
|
||||
|
||||
if (!vpr || help_mode)
|
||||
run("techmap -map +/xilinx/arith_map.v");
|
||||
else
|
||||
run("techmap -map +/xilinx/arith_map.v -D _EXPLICIT_CARRY");
|
||||
|
||||
run("hierarchy -check");
|
||||
run("opt -fast");
|
||||
}
|
||||
|
||||
if (check_label("map_cells"))
|
||||
{
|
||||
if (!nosrl) {
|
||||
if (!nosrl || help_mode) {
|
||||
// shregmap operates on bit-level flops, not word-level,
|
||||
// so break those down here
|
||||
Pass::call(design, "simplemap t:$dff t:$dffe");
|
||||
run("simplemap t:$dff t:$dffe", "(skip if '-nosrl')");
|
||||
// shregmap -tech xilinx can cope with $shiftx and $mux
|
||||
// cells for identifiying variable-length shift registers,
|
||||
// so attempt to convert $pmux-es to the former
|
||||
Pass::call(design, "pmux2shiftx");
|
||||
run("pmux2shiftx", "(skip if '-nosrl')");
|
||||
// pmux2shiftx can leave behind a $pmux with a single entry
|
||||
// -- need this to clean that up before shregmap
|
||||
Pass::call(design, "opt_expr -mux_undef");
|
||||
run("opt_expr -mux_undef", "(skip if '-nosrl')");
|
||||
// shregmap with '-tech xilinx' infers variable length shift regs
|
||||
Pass::call(design, "shregmap -tech xilinx -minlen 3");
|
||||
run("shregmap -tech xilinx -minlen 3", "(skip if '-nosrl')");
|
||||
}
|
||||
|
||||
Pass::call(design, "techmap -map +/xilinx/cells_map.v");
|
||||
Pass::call(design, "clean");
|
||||
run("techmap -map +/xilinx/cells_map.v");
|
||||
run("clean");
|
||||
}
|
||||
|
||||
if (check_label(active, run_from, run_to, "map_luts"))
|
||||
if (check_label("map_luts"))
|
||||
{
|
||||
Pass::call(design, "opt -full");
|
||||
Pass::call(design, "techmap -map +/techmap.v -D _NO_POS_SR -map +/xilinx/ff_map.v");
|
||||
Pass::call(design, "abc -luts 2:2,3,6:5,10,20" + string(retime ? " -dff" : ""));
|
||||
Pass::call(design, "clean");
|
||||
run("opt -full");
|
||||
run("techmap -map +/techmap.v -D _NO_POS_SR -map +/xilinx/ff_map.v");
|
||||
if (help_mode)
|
||||
run("abc -luts 2:2,3,6:5,10,20 [-dff]");
|
||||
else
|
||||
run("abc -luts 2:2,3,6:5,10,20" + string(retime ? " -dff" : ""));
|
||||
run("clean");
|
||||
// This shregmap call infers fixed length shift registers after abc
|
||||
// has performed any necessary retiming
|
||||
if (!nosrl)
|
||||
Pass::call(design, "shregmap -minlen 3 -init -params -enpol any_or_none");
|
||||
Pass::call(design, "techmap -map +/xilinx/lut_map.v -map +/xilinx/ff_map.v -map +/xilinx/cells_map.v");
|
||||
Pass::call(design, "dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT -ff FDSE Q INIT "
|
||||
if (!nosrl || help_mode)
|
||||
run("shregmap -minlen 3 -init -params -enpol any_or_none", "(skip if '-nosrl')");
|
||||
run("techmap -map +/xilinx/lut_map.v -map +/xilinx/ff_map.v -map +/xilinx/cells_map.v");
|
||||
run("dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT -ff FDSE Q INIT "
|
||||
"-ff FDRE_1 Q INIT -ff FDCE_1 Q INIT -ff FDPE_1 Q INIT -ff FDSE_1 Q INIT");
|
||||
Pass::call(design, "clean");
|
||||
run("clean");
|
||||
}
|
||||
|
||||
if (check_label(active, run_from, run_to, "check"))
|
||||
if (check_label("check"))
|
||||
{
|
||||
Pass::call(design, "hierarchy -check");
|
||||
Pass::call(design, "stat");
|
||||
Pass::call(design, "check -noinit");
|
||||
run("hierarchy -check");
|
||||
run("stat");
|
||||
run("check -noinit");
|
||||
}
|
||||
|
||||
if (check_label(active, run_from, run_to, "edif"))
|
||||
if (check_label("edif"))
|
||||
{
|
||||
if (!edif_file.empty())
|
||||
Pass::call(design, stringf("write_edif -pvector bra %s", edif_file.c_str()));
|
||||
}
|
||||
if (check_label(active, run_from, run_to, "blif"))
|
||||
{
|
||||
if (!blif_file.empty())
|
||||
Pass::call(design, stringf("write_blif %s", edif_file.c_str()));
|
||||
if (!edif_file.empty() || help_mode)
|
||||
run(stringf("write_edif -pvector bra %s", edif_file.c_str()));
|
||||
}
|
||||
|
||||
log_pop();
|
||||
if (check_label("blif"))
|
||||
{
|
||||
if (!blif_file.empty() || help_mode)
|
||||
run(stringf("write_blif %s", edif_file.c_str()));
|
||||
}
|
||||
}
|
||||
} SynthXilinxPass;
|
||||
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
module top
|
||||
(
|
||||
input [7:0] data_a,
|
||||
input [6:1] addr_a,
|
||||
input we_a, clk,
|
||||
output reg [7:0] q_a
|
||||
);
|
||||
// Declare the RAM variable
|
||||
reg [7:0] ram[63:0];
|
||||
|
||||
// Port A
|
||||
always @ (posedge clk)
|
||||
begin
|
||||
if (we_a)
|
||||
begin
|
||||
ram[addr_a] <= data_a;
|
||||
q_a <= data_a;
|
||||
end
|
||||
q_a <= ram[addr_a];
|
||||
end
|
||||
|
||||
endmodule
|
|
@ -16,6 +16,7 @@ operators.v $pow
|
|||
partsel.v drops modules
|
||||
process.v drops modules
|
||||
realexpr.v drops modules
|
||||
retime.v Initial value (11110101) for (retime_test.ff) not supported
|
||||
scopes.v original verilog issues ( -x where x isn't declared signed)
|
||||
sincos.v $adff
|
||||
specify.v no code (empty module generates error
|
||||
|
|
Loading…
Reference in New Issue