Merge branch 'YosysHQ:main' into main

This commit is contained in:
Akash Levy 2025-09-22 17:47:23 -07:00 committed by GitHub
commit d16ca47549
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
21 changed files with 274 additions and 120 deletions

View File

@ -180,7 +180,7 @@ ifeq ($(OS), Haiku)
CXXFLAGS += -D_DEFAULT_SOURCE
endif
YOSYS_VER := 0.57+157
YOSYS_VER := 0.57+178
YOSYS_MAJOR := $(shell echo $(YOSYS_VER) | cut -d'.' -f1)
YOSYS_MINOR := $(shell echo $(YOSYS_VER) | cut -d'.' -f2)
YOSYS_COMMIT := $(shell echo $(YOSYS_VER) | cut -d'.' -f3)
@ -949,6 +949,7 @@ MK_TEST_DIRS += tests/sim
MK_TEST_DIRS += tests/svtypes
MK_TEST_DIRS += tests/techmap
MK_TEST_DIRS += tests/various
MK_TEST_DIRS += tests/rtlil
ifeq ($(ENABLE_VERIFIC),1)
ifneq ($(YOSYS_NOVERIFIC),1)
MK_TEST_DIRS += tests/verific

View File

@ -24,12 +24,23 @@
#include "rtlil_backend.h"
#include "kernel/yosys.h"
#include "kernel/utils.h"
#include <errno.h>
#include <iterator>
USING_YOSYS_NAMESPACE
using namespace RTLIL_BACKEND;
YOSYS_NAMESPACE_BEGIN
void RTLIL_BACKEND::dump_attributes(std::ostream &f, std::string indent, const RTLIL::AttrObject *obj)
{
for (const auto& [name, value] : reversed(obj->attributes)) {
f << stringf("%s" "attribute %s ", indent, name);
dump_const(f, value);
f << stringf("\n");
}
}
void RTLIL_BACKEND::dump_const(std::ostream &f, const RTLIL::Const &data, int width, int offset, bool autoint)
{
if (width < 0)
@ -110,8 +121,8 @@ void RTLIL_BACKEND::dump_sigspec(std::ostream &f, const RTLIL::SigSpec &sig, boo
dump_sigchunk(f, sig.as_chunk(), autoint);
} else {
f << stringf("{ ");
for (auto it = sig.chunks().rbegin(); it != sig.chunks().rend(); ++it) {
dump_sigchunk(f, *it, false);
for (const auto& chunk : reversed(sig.chunks())) {
dump_sigchunk(f, chunk, false);
f << stringf(" ");
}
f << stringf("}");
@ -120,14 +131,10 @@ void RTLIL_BACKEND::dump_sigspec(std::ostream &f, const RTLIL::SigSpec &sig, boo
void RTLIL_BACKEND::dump_wire(std::ostream &f, std::string indent, const RTLIL::Wire *wire)
{
for (auto &it : wire->attributes) {
f << stringf("%s" "attribute %s ", indent, it.first);
dump_const(f, it.second);
f << stringf("\n");
}
dump_attributes(f, indent, wire);
if (wire->driverCell_) {
f << stringf("%s" "# driver %s %s\n", indent,
wire->driverCell()->name.c_str(), wire->driverPort().c_str());
wire->driverCell()->name, wire->driverPort());
}
f << stringf("%s" "wire ", indent);
if (wire->width != 1)
@ -149,11 +156,7 @@ void RTLIL_BACKEND::dump_wire(std::ostream &f, std::string indent, const RTLIL::
void RTLIL_BACKEND::dump_memory(std::ostream &f, std::string indent, const RTLIL::Memory *memory)
{
for (auto &it : memory->attributes) {
f << stringf("%s" "attribute %s ", indent, it.first);
dump_const(f, it.second);
f << stringf("\n");
}
dump_attributes(f, indent, memory);
f << stringf("%s" "memory ", indent);
if (memory->width != 1)
f << stringf("width %d ", memory->width);
@ -166,23 +169,19 @@ void RTLIL_BACKEND::dump_memory(std::ostream &f, std::string indent, const RTLIL
void RTLIL_BACKEND::dump_cell(std::ostream &f, std::string indent, const RTLIL::Cell *cell)
{
for (auto &it : cell->attributes) {
f << stringf("%s" "attribute %s ", indent, it.first);
dump_const(f, it.second);
f << stringf("\n");
}
dump_attributes(f, indent, cell);
f << stringf("%s" "cell %s %s\n", indent, cell->type, cell->name);
for (auto &it : cell->parameters) {
for (const auto& [name, param] : reversed(cell->parameters)) {
f << stringf("%s parameter%s%s %s ", indent,
(it.second.flags & RTLIL::CONST_FLAG_SIGNED) != 0 ? " signed" : "",
(it.second.flags & RTLIL::CONST_FLAG_REAL) != 0 ? " real" : "",
it.first.c_str());
dump_const(f, it.second);
(param.flags & RTLIL::CONST_FLAG_SIGNED) != 0 ? " signed" : "",
(param.flags & RTLIL::CONST_FLAG_REAL) != 0 ? " real" : "",
name);
dump_const(f, param);
f << stringf("\n");
}
for (auto &it : cell->connections()) {
f << stringf("%s connect %s ", indent, it.first);
dump_sigspec(f, it.second);
for (const auto& [port, sig] : reversed(cell->connections_)) {
f << stringf("%s connect %s ", indent, port);
dump_sigspec(f, sig);
f << stringf("\n");
}
f << stringf("%s" "end\n", indent);
@ -190,47 +189,38 @@ void RTLIL_BACKEND::dump_cell(std::ostream &f, std::string indent, const RTLIL::
void RTLIL_BACKEND::dump_proc_case_body(std::ostream &f, std::string indent, const RTLIL::CaseRule *cs)
{
for (auto it = cs->actions.begin(); it != cs->actions.end(); ++it)
{
for (const auto& [lhs, rhs] : cs->actions) {
f << stringf("%s" "assign ", indent);
dump_sigspec(f, it->first);
dump_sigspec(f, lhs);
f << stringf(" ");
dump_sigspec(f, it->second);
dump_sigspec(f, rhs);
f << stringf("\n");
}
for (auto it = cs->switches.begin(); it != cs->switches.end(); ++it)
dump_proc_switch(f, indent, *it);
for (const auto& sw : cs->switches)
dump_proc_switch(f, indent, sw);
}
void RTLIL_BACKEND::dump_proc_switch(std::ostream &f, std::string indent, const RTLIL::SwitchRule *sw)
{
for (auto it = sw->attributes.begin(); it != sw->attributes.end(); ++it) {
f << stringf("%s" "attribute %s ", indent, it->first);
dump_const(f, it->second);
f << stringf("\n");
}
dump_attributes(f, indent, sw);
f << stringf("%s" "switch ", indent);
dump_sigspec(f, sw->signal);
f << stringf("\n");
for (auto it = sw->cases.begin(); it != sw->cases.end(); ++it)
for (const auto case_ : sw->cases)
{
for (auto ait = (*it)->attributes.begin(); ait != (*it)->attributes.end(); ++ait) {
f << stringf("%s attribute %s ", indent, ait->first);
dump_const(f, ait->second);
f << stringf("\n");
}
dump_attributes(f, indent, case_);
f << stringf("%s case ", indent);
for (size_t i = 0; i < (*it)->compare.size(); i++) {
for (size_t i = 0; i < case_->compare.size(); i++) {
if (i > 0)
f << stringf(" , ");
dump_sigspec(f, (*it)->compare[i]);
dump_sigspec(f, case_->compare[i]);
}
f << stringf("\n");
dump_proc_case_body(f, indent + " ", *it);
dump_proc_case_body(f, indent + " ", case_);
}
f << stringf("%s" "end\n", indent);
@ -253,20 +243,16 @@ void RTLIL_BACKEND::dump_proc_sync(std::ostream &f, std::string indent, const RT
case RTLIL::STi: f << stringf("init\n"); break;
}
for (auto &it: sy->actions) {
for (const auto& [lhs, rhs] : sy->actions) {
f << stringf("%s update ", indent);
dump_sigspec(f, it.first);
dump_sigspec(f, lhs);
f << stringf(" ");
dump_sigspec(f, it.second);
dump_sigspec(f, rhs);
f << stringf("\n");
}
for (auto &it: sy->mem_write_actions) {
for (auto it2 = it.attributes.begin(); it2 != it.attributes.end(); ++it2) {
f << stringf("%s attribute %s ", indent, it2->first);
dump_const(f, it2->second);
f << stringf("\n");
}
dump_attributes(f, indent, &it);
f << stringf("%s memwr %s ", indent, it.memid);
dump_sigspec(f, it.address);
f << stringf(" ");
@ -281,15 +267,11 @@ void RTLIL_BACKEND::dump_proc_sync(std::ostream &f, std::string indent, const RT
void RTLIL_BACKEND::dump_proc(std::ostream &f, std::string indent, const RTLIL::Process *proc)
{
for (auto it = proc->attributes.begin(); it != proc->attributes.end(); ++it) {
f << stringf("%s" "attribute %s ", indent, it->first);
dump_const(f, it->second);
f << stringf("\n");
}
dump_attributes(f, indent, proc);
f << stringf("%s" "process %s\n", indent, proc->name);
dump_proc_case_body(f, indent + " ", &proc->root_case);
for (auto it = proc->syncs.begin(); it != proc->syncs.end(); ++it)
dump_proc_sync(f, indent + " ", *it);
for (auto* sync : proc->syncs)
dump_proc_sync(f, indent + " ", sync);
f << stringf("%s" "end\n", indent);
}
@ -309,11 +291,7 @@ void RTLIL_BACKEND::dump_module(std::ostream &f, std::string indent, RTLIL::Modu
if (print_header)
{
for (auto it = module->attributes.begin(); it != module->attributes.end(); ++it) {
f << stringf("%s" "attribute %s ", indent, it->first);
dump_const(f, it->second);
f << stringf("\n");
}
dump_attributes(f, indent, module);
f << stringf("%s" "module %s\n", indent, module->name);
@ -335,40 +313,40 @@ void RTLIL_BACKEND::dump_module(std::ostream &f, std::string indent, RTLIL::Modu
if (print_body)
{
for (auto it : module->wires())
if (!only_selected || design->selected(module, it)) {
for (const auto& [_, wire] : reversed(module->wires_))
if (!only_selected || design->selected(module, wire)) {
if (only_selected)
f << stringf("\n");
dump_wire(f, indent + " ", it);
dump_wire(f, indent + " ", wire);
}
for (auto it : module->memories)
if (!only_selected || design->selected(module, it.second)) {
for (const auto& [_, mem] : reversed(module->memories))
if (!only_selected || design->selected(module, mem)) {
if (only_selected)
f << stringf("\n");
dump_memory(f, indent + " ", it.second);
dump_memory(f, indent + " ", mem);
}
for (auto it : module->cells())
if (!only_selected || design->selected(module, it)) {
for (const auto& [_, cell] : reversed(module->cells_))
if (!only_selected || design->selected(module, cell)) {
if (only_selected)
f << stringf("\n");
dump_cell(f, indent + " ", it);
dump_cell(f, indent + " ", cell);
}
for (auto it : module->processes)
if (!only_selected || design->selected(module, it.second)) {
for (const auto& [_, process] : reversed(module->processes))
if (!only_selected || design->selected(module, process)) {
if (only_selected)
f << stringf("\n");
dump_proc(f, indent + " ", it.second);
dump_proc(f, indent + " ", process);
}
bool first_conn_line = true;
for (auto it = module->connections().begin(); it != module->connections().end(); ++it) {
for (const auto& [lhs, rhs] : module->connections()) {
bool show_conn = !only_selected || design->selected_whole_module(module->name);
if (!show_conn) {
RTLIL::SigSpec sigs = it->first;
sigs.append(it->second);
RTLIL::SigSpec sigs = lhs;
sigs.append(rhs);
for (auto &c : sigs.chunks()) {
if (c.wire == NULL || !design->selected(module, c.wire))
continue;
@ -378,7 +356,7 @@ void RTLIL_BACKEND::dump_module(std::ostream &f, std::string indent, RTLIL::Modu
if (show_conn) {
if (only_selected && first_conn_line)
f << stringf("\n");
dump_conn(f, indent + " ", it->first, it->second);
dump_conn(f, indent + " ", lhs, rhs);
first_conn_line = false;
}
}
@ -394,7 +372,7 @@ void RTLIL_BACKEND::dump_design(std::ostream &f, RTLIL::Design *design, bool onl
if (!flag_m) {
int count_selected_mods = 0;
for (auto module : design->modules()) {
for (auto* module : design->modules()) {
if (design->selected_whole_module(module->name))
flag_m = true;
if (design->selected(module))
@ -410,7 +388,7 @@ void RTLIL_BACKEND::dump_design(std::ostream &f, RTLIL::Design *design, bool onl
f << stringf("autoidx %d\n", autoidx);
}
for (auto module : design->modules()) {
for (const auto& [_, module] : reversed(design->modules_)) {
if (!only_selected || design->selected(module)) {
if (only_selected)
f << stringf("\n");
@ -438,10 +416,14 @@ struct RTLILBackend : public Backend {
log(" -selected\n");
log(" only write selected parts of the design.\n");
log("\n");
log(" -sort\n");
log(" sort design in-place (used to be default).\n");
log("\n");
}
void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) override
{
bool selected = false;
bool do_sort = false;
log_header(design, "Executing RTLIL backend.\n");
@ -452,14 +434,19 @@ struct RTLILBackend : public Backend {
selected = true;
continue;
}
if (arg == "-sort") {
do_sort = true;
continue;
}
break;
}
extra_args(f, filename, args, argidx);
design->sort();
log("Output filename: %s\n", filename);
if (do_sort)
design->sort();
*f << stringf("# Generated by %s\n", yosys_maybe_version());
RTLIL_BACKEND::dump_design(*f, design, selected, true, false);
}
@ -528,7 +515,7 @@ struct DumpPass : public Pass {
if (!empty) {
rewrite_filename(filename);
std::ofstream *ff = new std::ofstream;
ff->open(filename.c_str(), append ? std::ofstream::app : std::ofstream::trunc);
ff->open(filename, append ? std::ofstream::app : std::ofstream::trunc);
if (ff->fail()) {
delete ff;
log_error("Can't open file `%s' for writing: %s\n", filename, strerror(errno));

View File

@ -31,6 +31,7 @@
YOSYS_NAMESPACE_BEGIN
namespace RTLIL_BACKEND {
void dump_attributes(std::ostream &f, std::string indent, const RTLIL::AttrObject *obj);
void dump_const(std::ostream &f, const RTLIL::Const &data, int width = -1, int offset = 0, bool autoint = true);
void dump_sigchunk(std::ostream &f, const RTLIL::SigChunk &chunk, bool autoint = true);
void dump_sigspec(std::ostream &f, const RTLIL::SigSpec &sig, bool autoint = true);

View File

@ -229,6 +229,10 @@ struct VerilogFrontend : public Frontend {
log(" add 'dir' to the directories which are used when searching include\n");
log(" files\n");
log("\n");
log(" -relativeshare\n");
log(" use paths relative to share directory for source locations\n");
log(" where possible (experimental).\n");
log("\n");
log("The command 'verilog_defaults' can be used to register default options for\n");
log("subsequent calls to 'read_verilog'.\n");
log("\n");
@ -273,6 +277,7 @@ struct VerilogFrontend : public Frontend {
bool flag_nowb = false;
bool flag_nosynthesis = false;
bool flag_yydebug = false;
bool flag_relative_share = false;
define_map_t defines_map;
std::list<std::string> include_dirs;
@ -450,6 +455,11 @@ struct VerilogFrontend : public Frontend {
attributes.push_back(RTLIL::escape_id(args[++argidx]));
continue;
}
if (arg == "-relativeshare") {
flag_relative_share = true;
log_experimental("read_verilog -relativeshare");
continue;
}
if (arg == "-D" && argidx+1 < args.size()) {
std::string name = args[++argidx], value;
size_t equal = name.find('=');
@ -490,6 +500,13 @@ struct VerilogFrontend : public Frontend {
log("Parsing %s%s input from `%s' to AST representation.\n",
parse_mode.formal ? "formal " : "", parse_mode.sv ? "SystemVerilog" : "Verilog", filename.c_str());
log("verilog frontend filename %s\n", filename.c_str());
if (flag_relative_share) {
auto share_path = proc_share_dirname();
if (filename.substr(0, share_path.length()) == share_path)
filename = std::string("+/") + filename.substr(share_path.length());
log("new filename %s\n", filename.c_str());
}
AST::sv_mode_but_global_and_used_for_literally_one_condition = parse_mode.sv;
std::string code_after_preproc;

View File

@ -570,13 +570,16 @@ public:
int index;
const_iterator(const dict *ptr, int index) : ptr(ptr), index(index) { }
public:
typedef std::forward_iterator_tag iterator_category;
typedef std::bidirectional_iterator_tag iterator_category;
typedef std::pair<K, T> value_type;
typedef ptrdiff_t difference_type;
typedef std::pair<K, T>* pointer;
typedef std::pair<K, T>& reference;
typedef const std::pair<K, T>* pointer;
typedef const std::pair<K, T>& reference;
const_iterator() { }
const_iterator operator++() { index--; return *this; }
const_iterator operator++(int) { const_iterator tmp = *this; index--; return tmp; }
const_iterator operator--() { index++; return *this; }
const_iterator operator--(int) { const_iterator tmp = *this; index++; return tmp; }
const_iterator operator+=(int amt) { index -= amt; return *this; }
bool operator<(const const_iterator &other) const { return index > other.index; }
bool operator==(const const_iterator &other) const { return index == other.index; }
@ -610,6 +613,13 @@ public:
const std::pair<K, T> *operator->() const { return &ptr->entries[index].udata; }
operator const_iterator() const { return const_iterator(ptr, index); }
};
using reverse_iterator = std::reverse_iterator<const_iterator>;
reverse_iterator rbegin() const {
return std::make_reverse_iterator(end());
}
reverse_iterator rend() const {
return std::make_reverse_iterator(begin());
}
constexpr dict()
{
@ -859,7 +869,7 @@ public:
const_iterator begin() const { return const_iterator(this, int(entries.size())-1); }
const_iterator element(int n) const { return const_iterator(this, int(entries.size())-1-n); }
const_iterator end() const { return const_iterator(nullptr, -1); }
const_iterator end() const { return const_iterator(this, -1); }
};
template<typename K, typename OPS>

View File

@ -119,6 +119,7 @@ extern int log_make_debug;
extern int log_force_debug;
extern int log_debug_suppressed;
[[deprecated]]
[[noreturn]] void logv_file_error(const string &filename, int lineno, const char *format, va_list ap);
void set_verific_logging(void (*cb)(int msg_type, const char *message_id, const char* file_path, unsigned int left_line, unsigned int left_col, unsigned int right_line, unsigned int right_col, const char *msg));

View File

@ -5957,6 +5957,7 @@ RTLIL::CaseRule *RTLIL::CaseRule::clone() const
RTLIL::CaseRule *new_caserule = new RTLIL::CaseRule;
new_caserule->compare = compare;
new_caserule->actions = actions;
new_caserule->attributes = attributes;
for (auto &it : switches)
new_caserule->switches.push_back(it->clone());
return new_caserule;

View File

@ -21,6 +21,7 @@
// do not depend on any other components of yosys (except stuff like log_*).
#include "kernel/yosys.h"
#include <iterator>
#ifndef UTILS_H
#define UTILS_H
@ -276,6 +277,16 @@ inline int ceil_log2(int x)
#endif
}
template <typename T>
auto reversed(const T& container) {
struct reverse_view {
const T& cont;
auto begin() const { return cont.rbegin(); }
auto end() const { return cont.rend(); }
};
return reverse_view{container};
}
YOSYS_NAMESPACE_END
#endif

View File

@ -122,8 +122,6 @@ struct BugpointPass : public Pass {
int run_yosys(RTLIL::Design *design, string runner, string yosys_cmd, string yosys_arg, string suffix, bool catch_err)
{
design->sort();
string bugpoint_file = "bugpoint-case";
if (suffix.size())
bugpoint_file += stringf(".%.8s", suffix);

View File

@ -295,6 +295,7 @@ struct RunAbcState {
struct AbcModuleState {
RunAbcState run_abc;
int state_index;
int map_autoidx = 0;
std::vector<RTLIL::SigBit> signal_bits;
dict<RTLIL::SigBit, int> signal_map;
@ -309,8 +310,8 @@ struct AbcModuleState {
int undef_bits_lost = 0;
AbcModuleState(const AbcConfig &config, FfInitVals &initvals)
: run_abc(config), initvals(initvals) {}
AbcModuleState(const AbcConfig &config, FfInitVals &initvals, int state_index)
: run_abc(config), state_index(state_index), initvals(initvals) {}
AbcModuleState(AbcModuleState&&) = delete;
int map_signal(const AbcSigMap &assign_map, RTLIL::SigBit bit, gate_type_t gate_type = G(NONE), int in1 = -1, int in2 = -1, int in3 = -1, int in4 = -1);
@ -2458,7 +2459,7 @@ struct AbcPass : public Pass {
std::vector<RTLIL::Cell*> cells = mod->selected_cells();
assign_cell_connection_ports(mod, {&cells}, assign_map);
AbcModuleState state(config, initvals);
AbcModuleState state(config, initvals, 0);
state.prepare_module(design, mod, assign_map, cells, dff_mode, clk_str);
ConcurrentStack<AbcProcess> process_pool;
state.run_abc.run(process_pool);
@ -2634,7 +2635,6 @@ struct AbcPass : public Pass {
int num_worker_threads = ThreadPool::pool_size(1, max_threads);
ConcurrentQueue<std::unique_ptr<AbcModuleState>> work_queue(num_worker_threads);
ConcurrentQueue<std::unique_ptr<AbcModuleState>> work_finished_queue;
int work_finished_count = 0;
ConcurrentStack<AbcProcess> process_pool;
ThreadPool worker_threads(num_worker_threads, [&](int){
while (std::optional<std::unique_ptr<AbcModuleState>> work =
@ -2644,15 +2644,25 @@ struct AbcPass : public Pass {
work_finished_queue.push_back(std::move(*work));
}
});
int state_index = 0;
int next_state_index_to_process = 0;
std::vector<std::unique_ptr<AbcModuleState>> work_finished_by_index;
work_finished_by_index.resize(assigned_cells.size());
int work_finished_count = 0;
for (auto &it : assigned_cells) {
// Process ABC results that have already finished before queueing another ABC.
// This should keep our memory usage down.
// Make sure we process the results in the order we expect. When we can
// process results before the next ABC run, do so, to keep memory usage low(er).
while (std::optional<std::unique_ptr<AbcModuleState>> work =
work_finished_queue.try_pop_front()) {
(*work)->extract(assign_map, design, mod);
work_finished_by_index[(*work)->state_index] = std::move(*work);
++work_finished_count;
}
std::unique_ptr<AbcModuleState> state = std::make_unique<AbcModuleState>(config, initvals);
while (work_finished_by_index[next_state_index_to_process] != nullptr) {
work_finished_by_index[next_state_index_to_process]->extract(assign_map, design, mod);
work_finished_by_index[next_state_index_to_process] = nullptr;
++next_state_index_to_process;
}
std::unique_ptr<AbcModuleState> state = std::make_unique<AbcModuleState>(config, initvals, state_index++);
state->clk_polarity = std::get<0>(it.first);
state->clk_sig = assign_map(std::get<1>(it.first));
state->en_polarity = std::get<2>(it.first);
@ -2671,12 +2681,17 @@ struct AbcPass : public Pass {
}
}
work_queue.close();
while (work_finished_count < static_cast<int>(assigned_cells.size())) {
while (work_finished_count < GetSize(assigned_cells)) {
std::optional<std::unique_ptr<AbcModuleState>> work =
work_finished_queue.pop_front();
(*work)->extract(assign_map, design, mod);
work_finished_by_index[(*work)->state_index] = std::move(*work);
++work_finished_count;
}
while (next_state_index_to_process < GetSize(work_finished_by_index)) {
work_finished_by_index[next_state_index_to_process]->extract(assign_map, design, mod);
work_finished_by_index[next_state_index_to_process] = nullptr;
++next_state_index_to_process;
}
}
if (config.cleanup) {

View File

@ -1042,6 +1042,10 @@ struct TechmapPass : public Pass {
log(" -dont_map <celltype>\n");
log(" leave the given cell type unmapped by ignoring any mapping rules for it\n");
log("\n");
log(" -relativeshare\n");
log(" use paths relative to share directory for source locations\n");
log(" where possible (experimental).\n");
log("\n");
log("When a module in the map file has the 'techmap_celltype' attribute set, it will\n");
log("match cells with a type that match the text value of this attribute. Otherwise\n");
log("the module name will be used to match the cell. Multiple space-separated cell\n");
@ -1195,6 +1199,11 @@ struct TechmapPass : public Pass {
verilog_frontend += " -I " + args[++argidx];
continue;
}
if (args[argidx] == "-relativeshare") {
verilog_frontend += " -relativeshare";
log_experimental("techmap -relativeshare");
continue;
}
if (args[argidx] == "-assert") {
worker.assert_mode = true;
continue;

View File

@ -47,7 +47,7 @@ struct RaiseErrorPass : public Pass {
extra_args(args, argidx, design, true);
RTLIL::NamedObject *err_obj = nullptr;
for (auto mod : design->all_selected_modules()) {
if (mod->has_attribute(ID::raise_error)) {
err_obj = mod->clone();

View File

@ -98,13 +98,17 @@ struct SynthPass : public ScriptPass {
log(" mapping library in the `techmap` step. this option can be\n");
log(" repeated.\n");
log("\n");
log(" -relativeshare\n");
log(" use paths relative to share directory for source locations\n");
log(" where possible (experimental).\n");
log("\n");
log("The following commands are executed by this synthesis command:\n");
help_script();
log("\n");
}
string top_module, fsm_opts, memory_opts, abc;
bool autotop, flatten, noalumacc, nofsm, noabc, noshare, flowmap, booth, hieropt;
bool autotop, flatten, noalumacc, nofsm, noabc, noshare, flowmap, booth, hieropt, relative_share;
int lut;
std::vector<std::string> techmap_maps;
@ -124,6 +128,7 @@ struct SynthPass : public ScriptPass {
flowmap = false;
booth = false;
hieropt = false;
relative_share = false;
abc = "abc";
techmap_maps.clear();
}
@ -211,6 +216,11 @@ struct SynthPass : public ScriptPass {
hieropt = true;
continue;
}
if (args[argidx] == "-relativeshare") {
relative_share = true;
log_experimental("synth -relativeshare");
continue;
}
break;
}
extra_args(args, argidx, design);
@ -239,6 +249,10 @@ struct SynthPass : public ScriptPass {
else
hieropt_flag = hieropt ? " -hier" : "";
std::string techmap_cmd = "techmap";
if (relative_share)
techmap_cmd += " -relativeshare";
if (check_label("begin")) {
if (help_mode) {
run("hierarchy -check [-top <top> | -auto-top]");
@ -268,9 +282,9 @@ struct SynthPass : public ScriptPass {
run("peepopt");
run("opt_clean");
if (help_mode)
run("techmap -map +/cmp2lut.v -map +/cmp2lcu.v", " (if -lut)");
run(techmap_cmd + " -map +/cmp2lut.v -map +/cmp2lcu.v", " (if -lut)");
else if (lut)
run(stringf("techmap -map +/cmp2lut.v -map +/cmp2lcu.v -D LUT_WIDTH=%d", lut));
run(stringf("%s -map +/cmp2lut.v -map +/cmp2lcu.v -D LUT_WIDTH=%d", techmap_cmd, lut));
if (booth || help_mode)
run("booth", " (if -booth)");
if (!noalumacc)
@ -287,22 +301,22 @@ struct SynthPass : public ScriptPass {
run("memory_map");
run("opt -full");
if (help_mode) {
run("techmap", " (unless -extra-map)");
run("techmap -map +/techmap.v -map <inject>", " (if -extra-map)");
run(techmap_cmd, " (unless -extra-map)");
run(techmap_cmd + " -map +/techmap.v -map <inject>", " (if -extra-map)");
} else {
std::string techmap_opts;
if (!techmap_maps.empty())
techmap_opts += " -map +/techmap.v";
for (auto fn : techmap_maps)
techmap_opts += stringf(" -map %s", fn);
run("techmap" + techmap_opts);
run(techmap_cmd + techmap_opts);
}
if (help_mode) {
run("techmap -map +/gate2lut.v", "(if -noabc and -lut)");
run(techmap_cmd + " -map +/gate2lut.v", "(if -noabc and -lut)");
run("clean; opt_lut", " (if -noabc and -lut)");
run("flowmap -maxlut K", " (if -flowmap and -lut)");
} else if (noabc && lut) {
run(stringf("techmap -map +/gate2lut.v -D LUT_WIDTH=%d", lut));
run(stringf("%s -map +/gate2lut.v -D LUT_WIDTH=%d", techmap_cmd, lut));
run("clean; opt_lut");
} else if (flowmap) {
run(stringf("flowmap -maxlut %d", lut));

View File

@ -69,7 +69,7 @@ struct SynthPass : public ScriptPass
log(" use the specified Verilog file for extra primitives (can be specified multiple\n");
log(" times).\n");
log("\n");
log(" -extra-map <techamp.v>\n");
log(" -extra-map <techmap.v>\n");
log(" use the specified Verilog file for extra techmap rules (can be specified multiple\n");
log(" times).\n");
log("\n");

View File

@ -22,34 +22,37 @@ logger -check-expected
# raise_error with int exits with status
design -load read
setattr -mod -unset raise_error def other
dump
bugpoint -suffix error -yosys ../../yosys -command raise_error -expect-return 7
select -assert-mod-count 1 =*
select -assert-mod-count 1 top
# raise_error -always still uses 'raise_error' attribute if possible
design -load read
setattr -mod -unset raise_error def other
bugpoint -suffix error -yosys ../../yosys -command "raise_error -always" -expect-return 7
select -assert-mod-count 1 =*
select -assert-mod-count 1 top
# raise_error with string prints message and exits with 1
design -load read
rename top abc
setattr -mod -unset raise_error top def
bugpoint -suffix error -yosys ../../yosys -command raise_error -grep "help me" -expect-return 1
select -assert-mod-count 1 =*
select -assert-mod-count 1 other
# raise_error with no value exits with 1
design -load read
rename def zzy
setattr -mod -unset raise_error top
delete other
bugpoint -suffix error -yosys ../../yosys -command raise_error -expect-return 1
select -assert-mod-count 1 =*
select -assert-mod-count 1 zzy
select -assert-mod-count 1 def
# raise_error -stderr prints to stderr and exits with 1
design -load read
rename top abc
setattr -mod -unset raise_error top def
bugpoint -suffix error -yosys ../../yosys -command "raise_error -stderr" -err-grep "help me" -expect-return 1
select -assert-mod-count 1 =*
select -assert-mod-count 1 other

View File

@ -24,7 +24,7 @@ def compile_cpp(in_path, out_path, args):
run(['g++', '-g', '-std=c++17'] + args + [str(in_path), '-o', str(out_path)])
def yosys_synth(verilog_file, rtlil_file):
yosys(f"read_verilog {quote(verilog_file)} ; prep ; write_rtlil {quote(rtlil_file)}")
yosys(f"read_verilog {quote(verilog_file)} ; prep ; setundef -undriven -undef ; write_rtlil {quote(rtlil_file)}")
# simulate an rtlil file with yosys, comparing with a given vcd file, and writing out the yosys simulation results into a second vcd file
def yosys_sim(rtlil_file, vcd_reference_file, vcd_out_file, preprocessing = ""):
@ -91,4 +91,4 @@ def test_print_graph(tmp_path):
tb_file = base_path / 'tests/functional/picorv32_tb.v'
cpu_file = base_path / 'tests/functional/picorv32.v'
# currently we only check that we can print the graph without getting an error, not that it prints anything sensibl
yosys(f"read_verilog {quote(tb_file)} {quote(cpu_file)}; prep -top gold; flatten; clk2fflogic; test_generic")
yosys(f"read_verilog {quote(tb_file)} {quote(cpu_file)}; prep -top gold; setundef -undriven -undef ; flatten; clk2fflogic; test_generic")

1
tests/rtlil/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/temp

40
tests/rtlil/everything.v Normal file
View File

@ -0,0 +1,40 @@
module alu(
input clk,
input [7:0] A,
input [7:0] B,
input [3:0] operation,
output reg [7:0] result,
output reg CF,
output reg ZF,
output reg SF
);
localparam ALU_OP_ADD = 4'b0000;
localparam ALU_OP_SUB = 4'b0001;
reg [8:0] tmp;
always @(posedge clk)
begin
case (operation)
ALU_OP_ADD :
tmp = A + B;
ALU_OP_SUB :
tmp = A - B;
endcase
CF <= tmp[8];
ZF <= tmp[7:0] == 0;
SF <= tmp[7];
result <= tmp[7:0];
end
endmodule
module foo(
input [7:0] a, input [7:0] b, output [7:0] y
);
wire [7:0] bb;
assign b = bb;
assign y = a + bb;
endmodule

View File

@ -0,0 +1,10 @@
set -euo pipefail
YS=../../yosys
mkdir -p temp
$YS -p "read_verilog -sv everything.v; write_rtlil temp/roundtrip-design-push.il; design -push; design -pop; write_rtlil temp/roundtrip-design-pop.il"
diff temp/roundtrip-design-push.il temp/roundtrip-design-pop.il
$YS -p "read_verilog -sv everything.v; write_rtlil temp/roundtrip-design-save.il; design -save foo; design -load foo; write_rtlil temp/roundtrip-design-load.il"
diff temp/roundtrip-design-save.il temp/roundtrip-design-load.il

View File

@ -0,0 +1,31 @@
set -euo pipefail
YS=../../yosys
mkdir -p temp
# non-POSIX sed -i inconsistency workaround
remove_empty_lines() {
local file="$1"
sed '/^$/d' "$file" > temp/tmp
mv temp/tmp "$file"
}
# write_rtlil and dump are equivalent
$YS -p "read_verilog -sv everything.v; copy alu zzz; proc zzz; dump -o temp/roundtrip-text.dump.il; write_rtlil temp/roundtrip-text.write.il"
remove_empty_lines temp/roundtrip-text.dump.il
remove_empty_lines temp/roundtrip-text.write.il
# Trim first line ("Generated by Yosys ...")
tail -n +2 temp/roundtrip-text.write.il > temp/roundtrip-text.write-nogen.il
diff temp/roundtrip-text.dump.il temp/roundtrip-text.write-nogen.il
# Loading and writing it out again doesn't change the RTLIL
$YS -p "read_rtlil temp/roundtrip-text.dump.il; write_rtlil temp/roundtrip-text.reload.il"
remove_empty_lines temp/roundtrip-text.reload.il
tail -n +2 temp/roundtrip-text.reload.il > temp/roundtrip-text.reload-nogen.il
diff temp/roundtrip-text.dump.il temp/roundtrip-text.reload-nogen.il
# Hashing differences don't change the RTLIL
$YS --hash-seed=2345678 -p "read_rtlil temp/roundtrip-text.dump.il; write_rtlil temp/roundtrip-text.reload-hash.il"
remove_empty_lines temp/roundtrip-text.reload-hash.il
tail -n +2 temp/roundtrip-text.reload-hash.il > temp/roundtrip-text.reload-hash-nogen.il
diff temp/roundtrip-text.dump.il temp/roundtrip-text.reload-hash-nogen.il

4
tests/rtlil/run-test.sh Executable file
View File

@ -0,0 +1,4 @@
#!/usr/bin/env bash
set -eu
source ../gen-tests-makefile.sh
generate_mk --bash