mirror of
https://github.com/YosysHQ/yosys
synced 2025-09-13 21:21:27 +00:00
Merge 9de931b902
into 012ddc2f1e
This commit is contained in:
commit
023f867044
21 changed files with 1730 additions and 107 deletions
1
Makefile
1
Makefile
|
@ -874,6 +874,7 @@ MK_TEST_DIRS += tests/sim
|
||||||
MK_TEST_DIRS += tests/svtypes
|
MK_TEST_DIRS += tests/svtypes
|
||||||
MK_TEST_DIRS += tests/techmap
|
MK_TEST_DIRS += tests/techmap
|
||||||
MK_TEST_DIRS += tests/various
|
MK_TEST_DIRS += tests/various
|
||||||
|
MK_TEST_DIRS += tests/rtlil
|
||||||
ifeq ($(ENABLE_VERIFIC),1)
|
ifeq ($(ENABLE_VERIFIC),1)
|
||||||
ifneq ($(YOSYS_NOVERIFIC),1)
|
ifneq ($(YOSYS_NOVERIFIC),1)
|
||||||
MK_TEST_DIRS += tests/verific
|
MK_TEST_DIRS += tests/verific
|
||||||
|
|
|
@ -24,12 +24,23 @@
|
||||||
|
|
||||||
#include "rtlil_backend.h"
|
#include "rtlil_backend.h"
|
||||||
#include "kernel/yosys.h"
|
#include "kernel/yosys.h"
|
||||||
|
#include "kernel/utils.h"
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <iterator>
|
||||||
|
|
||||||
USING_YOSYS_NAMESPACE
|
USING_YOSYS_NAMESPACE
|
||||||
using namespace RTLIL_BACKEND;
|
using namespace RTLIL_BACKEND;
|
||||||
YOSYS_NAMESPACE_BEGIN
|
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.c_str(), name.c_str());
|
||||||
|
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)
|
void RTLIL_BACKEND::dump_const(std::ostream &f, const RTLIL::Const &data, int width, int offset, bool autoint)
|
||||||
{
|
{
|
||||||
if (width < 0)
|
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);
|
dump_sigchunk(f, sig.as_chunk(), autoint);
|
||||||
} else {
|
} else {
|
||||||
f << stringf("{ ");
|
f << stringf("{ ");
|
||||||
for (auto it = sig.chunks().rbegin(); it != sig.chunks().rend(); ++it) {
|
for (const auto& chunk : reversed(sig.chunks())) {
|
||||||
dump_sigchunk(f, *it, false);
|
dump_sigchunk(f, chunk, false);
|
||||||
f << stringf(" ");
|
f << stringf(" ");
|
||||||
}
|
}
|
||||||
f << stringf("}");
|
f << stringf("}");
|
||||||
|
@ -120,11 +131,7 @@ 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)
|
void RTLIL_BACKEND::dump_wire(std::ostream &f, std::string indent, const RTLIL::Wire *wire)
|
||||||
{
|
{
|
||||||
for (auto &it : wire->attributes) {
|
dump_attributes(f, indent, wire);
|
||||||
f << stringf("%s" "attribute %s ", indent.c_str(), it.first.c_str());
|
|
||||||
dump_const(f, it.second);
|
|
||||||
f << stringf("\n");
|
|
||||||
}
|
|
||||||
if (wire->driverCell_) {
|
if (wire->driverCell_) {
|
||||||
f << stringf("%s" "# driver %s %s\n", indent.c_str(),
|
f << stringf("%s" "# driver %s %s\n", indent.c_str(),
|
||||||
wire->driverCell()->name.c_str(), wire->driverPort().c_str());
|
wire->driverCell()->name.c_str(), wire->driverPort().c_str());
|
||||||
|
@ -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)
|
void RTLIL_BACKEND::dump_memory(std::ostream &f, std::string indent, const RTLIL::Memory *memory)
|
||||||
{
|
{
|
||||||
for (auto &it : memory->attributes) {
|
dump_attributes(f, indent, memory);
|
||||||
f << stringf("%s" "attribute %s ", indent.c_str(), it.first.c_str());
|
|
||||||
dump_const(f, it.second);
|
|
||||||
f << stringf("\n");
|
|
||||||
}
|
|
||||||
f << stringf("%s" "memory ", indent.c_str());
|
f << stringf("%s" "memory ", indent.c_str());
|
||||||
if (memory->width != 1)
|
if (memory->width != 1)
|
||||||
f << stringf("width %d ", memory->width);
|
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)
|
void RTLIL_BACKEND::dump_cell(std::ostream &f, std::string indent, const RTLIL::Cell *cell)
|
||||||
{
|
{
|
||||||
for (auto &it : cell->attributes) {
|
dump_attributes(f, indent, cell);
|
||||||
f << stringf("%s" "attribute %s ", indent.c_str(), it.first.c_str());
|
|
||||||
dump_const(f, it.second);
|
|
||||||
f << stringf("\n");
|
|
||||||
}
|
|
||||||
f << stringf("%s" "cell %s %s\n", indent.c_str(), cell->type.c_str(), cell->name.c_str());
|
f << stringf("%s" "cell %s %s\n", indent.c_str(), cell->type.c_str(), cell->name.c_str());
|
||||||
for (auto &it : cell->parameters) {
|
for (const auto& [name, param] : reversed(cell->parameters)) {
|
||||||
f << stringf("%s parameter%s%s %s ", indent.c_str(),
|
f << stringf("%s parameter%s%s %s ", indent.c_str(),
|
||||||
(it.second.flags & RTLIL::CONST_FLAG_SIGNED) != 0 ? " signed" : "",
|
(param.flags & RTLIL::CONST_FLAG_SIGNED) != 0 ? " signed" : "",
|
||||||
(it.second.flags & RTLIL::CONST_FLAG_REAL) != 0 ? " real" : "",
|
(param.flags & RTLIL::CONST_FLAG_REAL) != 0 ? " real" : "",
|
||||||
it.first.c_str());
|
name.c_str());
|
||||||
dump_const(f, it.second);
|
dump_const(f, param);
|
||||||
f << stringf("\n");
|
f << stringf("\n");
|
||||||
}
|
}
|
||||||
for (auto &it : cell->connections()) {
|
for (const auto& [port, sig] : reversed(cell->connections_)) {
|
||||||
f << stringf("%s connect %s ", indent.c_str(), it.first.c_str());
|
f << stringf("%s connect %s ", indent.c_str(), port.c_str());
|
||||||
dump_sigspec(f, it.second);
|
dump_sigspec(f, sig);
|
||||||
f << stringf("\n");
|
f << stringf("\n");
|
||||||
}
|
}
|
||||||
f << stringf("%s" "end\n", indent.c_str());
|
f << stringf("%s" "end\n", indent.c_str());
|
||||||
|
@ -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)
|
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.c_str());
|
f << stringf("%s" "assign ", indent.c_str());
|
||||||
dump_sigspec(f, it->first);
|
dump_sigspec(f, lhs);
|
||||||
f << stringf(" ");
|
f << stringf(" ");
|
||||||
dump_sigspec(f, it->second);
|
dump_sigspec(f, rhs);
|
||||||
f << stringf("\n");
|
f << stringf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto it = cs->switches.begin(); it != cs->switches.end(); ++it)
|
for (const auto& sw : cs->switches)
|
||||||
dump_proc_switch(f, indent, *it);
|
dump_proc_switch(f, indent, sw);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RTLIL_BACKEND::dump_proc_switch(std::ostream &f, std::string indent, const RTLIL::SwitchRule *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) {
|
dump_attributes(f, indent, sw);
|
||||||
f << stringf("%s" "attribute %s ", indent.c_str(), it->first.c_str());
|
|
||||||
dump_const(f, it->second);
|
|
||||||
f << stringf("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
f << stringf("%s" "switch ", indent.c_str());
|
f << stringf("%s" "switch ", indent.c_str());
|
||||||
dump_sigspec(f, sw->signal);
|
dump_sigspec(f, sw->signal);
|
||||||
f << stringf("\n");
|
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) {
|
dump_attributes(f, indent, case_);
|
||||||
f << stringf("%s attribute %s ", indent.c_str(), ait->first.c_str());
|
|
||||||
dump_const(f, ait->second);
|
|
||||||
f << stringf("\n");
|
|
||||||
}
|
|
||||||
f << stringf("%s case ", indent.c_str());
|
f << stringf("%s case ", indent.c_str());
|
||||||
for (size_t i = 0; i < (*it)->compare.size(); i++) {
|
for (size_t i = 0; i < case_->compare.size(); i++) {
|
||||||
if (i > 0)
|
if (i > 0)
|
||||||
f << stringf(" , ");
|
f << stringf(" , ");
|
||||||
dump_sigspec(f, (*it)->compare[i]);
|
dump_sigspec(f, case_->compare[i]);
|
||||||
}
|
}
|
||||||
f << stringf("\n");
|
f << stringf("\n");
|
||||||
|
|
||||||
dump_proc_case_body(f, indent + " ", *it);
|
dump_proc_case_body(f, indent + " ", case_);
|
||||||
}
|
}
|
||||||
|
|
||||||
f << stringf("%s" "end\n", indent.c_str());
|
f << stringf("%s" "end\n", indent.c_str());
|
||||||
|
@ -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;
|
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.c_str());
|
f << stringf("%s update ", indent.c_str());
|
||||||
dump_sigspec(f, it.first);
|
dump_sigspec(f, lhs);
|
||||||
f << stringf(" ");
|
f << stringf(" ");
|
||||||
dump_sigspec(f, it.second);
|
dump_sigspec(f, rhs);
|
||||||
f << stringf("\n");
|
f << stringf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto &it: sy->mem_write_actions) {
|
for (auto &it: sy->mem_write_actions) {
|
||||||
for (auto it2 = it.attributes.begin(); it2 != it.attributes.end(); ++it2) {
|
dump_attributes(f, indent, &it);
|
||||||
f << stringf("%s attribute %s ", indent.c_str(), it2->first.c_str());
|
|
||||||
dump_const(f, it2->second);
|
|
||||||
f << stringf("\n");
|
|
||||||
}
|
|
||||||
f << stringf("%s memwr %s ", indent.c_str(), it.memid.c_str());
|
f << stringf("%s memwr %s ", indent.c_str(), it.memid.c_str());
|
||||||
dump_sigspec(f, it.address);
|
dump_sigspec(f, it.address);
|
||||||
f << stringf(" ");
|
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)
|
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) {
|
dump_attributes(f, indent, proc);
|
||||||
f << stringf("%s" "attribute %s ", indent.c_str(), it->first.c_str());
|
|
||||||
dump_const(f, it->second);
|
|
||||||
f << stringf("\n");
|
|
||||||
}
|
|
||||||
f << stringf("%s" "process %s\n", indent.c_str(), proc->name.c_str());
|
f << stringf("%s" "process %s\n", indent.c_str(), proc->name.c_str());
|
||||||
dump_proc_case_body(f, indent + " ", &proc->root_case);
|
dump_proc_case_body(f, indent + " ", &proc->root_case);
|
||||||
for (auto it = proc->syncs.begin(); it != proc->syncs.end(); ++it)
|
for (auto* sync : proc->syncs)
|
||||||
dump_proc_sync(f, indent + " ", *it);
|
dump_proc_sync(f, indent + " ", sync);
|
||||||
f << stringf("%s" "end\n", indent.c_str());
|
f << stringf("%s" "end\n", indent.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -309,11 +291,7 @@ void RTLIL_BACKEND::dump_module(std::ostream &f, std::string indent, RTLIL::Modu
|
||||||
|
|
||||||
if (print_header)
|
if (print_header)
|
||||||
{
|
{
|
||||||
for (auto it = module->attributes.begin(); it != module->attributes.end(); ++it) {
|
dump_attributes(f, indent, module);
|
||||||
f << stringf("%s" "attribute %s ", indent.c_str(), it->first.c_str());
|
|
||||||
dump_const(f, it->second);
|
|
||||||
f << stringf("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
f << stringf("%s" "module %s\n", indent.c_str(), module->name.c_str());
|
f << stringf("%s" "module %s\n", indent.c_str(), module->name.c_str());
|
||||||
|
|
||||||
|
@ -335,40 +313,40 @@ void RTLIL_BACKEND::dump_module(std::ostream &f, std::string indent, RTLIL::Modu
|
||||||
|
|
||||||
if (print_body)
|
if (print_body)
|
||||||
{
|
{
|
||||||
for (auto it : module->wires())
|
for (const auto& [_, wire] : reversed(module->wires_))
|
||||||
if (!only_selected || design->selected(module, it)) {
|
if (!only_selected || design->selected(module, wire)) {
|
||||||
if (only_selected)
|
if (only_selected)
|
||||||
f << stringf("\n");
|
f << stringf("\n");
|
||||||
dump_wire(f, indent + " ", it);
|
dump_wire(f, indent + " ", wire);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto it : module->memories)
|
for (const auto& [_, mem] : reversed(module->memories))
|
||||||
if (!only_selected || design->selected(module, it.second)) {
|
if (!only_selected || design->selected(module, mem)) {
|
||||||
if (only_selected)
|
if (only_selected)
|
||||||
f << stringf("\n");
|
f << stringf("\n");
|
||||||
dump_memory(f, indent + " ", it.second);
|
dump_memory(f, indent + " ", mem);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto it : module->cells())
|
for (const auto& [_, cell] : reversed(module->cells_))
|
||||||
if (!only_selected || design->selected(module, it)) {
|
if (!only_selected || design->selected(module, cell)) {
|
||||||
if (only_selected)
|
if (only_selected)
|
||||||
f << stringf("\n");
|
f << stringf("\n");
|
||||||
dump_cell(f, indent + " ", it);
|
dump_cell(f, indent + " ", cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto it : module->processes)
|
for (const auto& [_, process] : reversed(module->processes))
|
||||||
if (!only_selected || design->selected(module, it.second)) {
|
if (!only_selected || design->selected(module, process)) {
|
||||||
if (only_selected)
|
if (only_selected)
|
||||||
f << stringf("\n");
|
f << stringf("\n");
|
||||||
dump_proc(f, indent + " ", it.second);
|
dump_proc(f, indent + " ", process);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool first_conn_line = true;
|
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);
|
bool show_conn = !only_selected || design->selected_whole_module(module->name);
|
||||||
if (!show_conn) {
|
if (!show_conn) {
|
||||||
RTLIL::SigSpec sigs = it->first;
|
RTLIL::SigSpec sigs = lhs;
|
||||||
sigs.append(it->second);
|
sigs.append(rhs);
|
||||||
for (auto &c : sigs.chunks()) {
|
for (auto &c : sigs.chunks()) {
|
||||||
if (c.wire == NULL || !design->selected(module, c.wire))
|
if (c.wire == NULL || !design->selected(module, c.wire))
|
||||||
continue;
|
continue;
|
||||||
|
@ -378,7 +356,7 @@ void RTLIL_BACKEND::dump_module(std::ostream &f, std::string indent, RTLIL::Modu
|
||||||
if (show_conn) {
|
if (show_conn) {
|
||||||
if (only_selected && first_conn_line)
|
if (only_selected && first_conn_line)
|
||||||
f << stringf("\n");
|
f << stringf("\n");
|
||||||
dump_conn(f, indent + " ", it->first, it->second);
|
dump_conn(f, indent + " ", lhs, rhs);
|
||||||
first_conn_line = false;
|
first_conn_line = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -394,7 +372,7 @@ void RTLIL_BACKEND::dump_design(std::ostream &f, RTLIL::Design *design, bool onl
|
||||||
|
|
||||||
if (!flag_m) {
|
if (!flag_m) {
|
||||||
int count_selected_mods = 0;
|
int count_selected_mods = 0;
|
||||||
for (auto module : design->modules()) {
|
for (auto* module : design->modules()) {
|
||||||
if (design->selected_whole_module(module->name))
|
if (design->selected_whole_module(module->name))
|
||||||
flag_m = true;
|
flag_m = true;
|
||||||
if (design->selected(module))
|
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);
|
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 || design->selected(module)) {
|
||||||
if (only_selected)
|
if (only_selected)
|
||||||
f << stringf("\n");
|
f << stringf("\n");
|
||||||
|
@ -438,10 +416,14 @@ struct RTLILBackend : public Backend {
|
||||||
log(" -selected\n");
|
log(" -selected\n");
|
||||||
log(" only write selected parts of the design.\n");
|
log(" only write selected parts of the design.\n");
|
||||||
log("\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
|
void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) override
|
||||||
{
|
{
|
||||||
bool selected = false;
|
bool selected = false;
|
||||||
|
bool do_sort = false;
|
||||||
|
|
||||||
log_header(design, "Executing RTLIL backend.\n");
|
log_header(design, "Executing RTLIL backend.\n");
|
||||||
|
|
||||||
|
@ -452,14 +434,19 @@ struct RTLILBackend : public Backend {
|
||||||
selected = true;
|
selected = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (arg == "-sort") {
|
||||||
|
do_sort = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
extra_args(f, filename, args, argidx);
|
extra_args(f, filename, args, argidx);
|
||||||
|
|
||||||
design->sort();
|
|
||||||
|
|
||||||
log("Output filename: %s\n", filename.c_str());
|
log("Output filename: %s\n", filename.c_str());
|
||||||
|
|
||||||
|
if (do_sort)
|
||||||
|
design->sort();
|
||||||
|
|
||||||
*f << stringf("# Generated by %s\n", yosys_maybe_version());
|
*f << stringf("# Generated by %s\n", yosys_maybe_version());
|
||||||
RTLIL_BACKEND::dump_design(*f, design, selected, true, false);
|
RTLIL_BACKEND::dump_design(*f, design, selected, true, false);
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
YOSYS_NAMESPACE_BEGIN
|
YOSYS_NAMESPACE_BEGIN
|
||||||
|
|
||||||
namespace RTLIL_BACKEND {
|
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_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_sigchunk(std::ostream &f, const RTLIL::SigChunk &chunk, bool autoint = true);
|
||||||
void dump_sigspec(std::ostream &f, const RTLIL::SigSpec &sig, bool autoint = true);
|
void dump_sigspec(std::ostream &f, const RTLIL::SigSpec &sig, bool autoint = true);
|
||||||
|
|
|
@ -229,6 +229,10 @@ struct VerilogFrontend : public Frontend {
|
||||||
log(" add 'dir' to the directories which are used when searching include\n");
|
log(" add 'dir' to the directories which are used when searching include\n");
|
||||||
log(" files\n");
|
log(" files\n");
|
||||||
log("\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("The command 'verilog_defaults' can be used to register default options for\n");
|
||||||
log("subsequent calls to 'read_verilog'.\n");
|
log("subsequent calls to 'read_verilog'.\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
|
@ -273,6 +277,7 @@ struct VerilogFrontend : public Frontend {
|
||||||
bool flag_nowb = false;
|
bool flag_nowb = false;
|
||||||
bool flag_nosynthesis = false;
|
bool flag_nosynthesis = false;
|
||||||
bool flag_yydebug = false;
|
bool flag_yydebug = false;
|
||||||
|
bool flag_relative_share = false;
|
||||||
define_map_t defines_map;
|
define_map_t defines_map;
|
||||||
|
|
||||||
std::list<std::string> include_dirs;
|
std::list<std::string> include_dirs;
|
||||||
|
@ -450,6 +455,11 @@ struct VerilogFrontend : public Frontend {
|
||||||
attributes.push_back(RTLIL::escape_id(args[++argidx]));
|
attributes.push_back(RTLIL::escape_id(args[++argidx]));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (arg == "-relativeshare") {
|
||||||
|
flag_relative_share = true;
|
||||||
|
log_experimental("read_verilog -relativeshare");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (arg == "-D" && argidx+1 < args.size()) {
|
if (arg == "-D" && argidx+1 < args.size()) {
|
||||||
std::string name = args[++argidx], value;
|
std::string name = args[++argidx], value;
|
||||||
size_t equal = name.find('=');
|
size_t equal = name.find('=');
|
||||||
|
@ -490,6 +500,13 @@ struct VerilogFrontend : public Frontend {
|
||||||
log("Parsing %s%s input from `%s' to AST representation.\n",
|
log("Parsing %s%s input from `%s' to AST representation.\n",
|
||||||
parse_mode.formal ? "formal " : "", parse_mode.sv ? "SystemVerilog" : "Verilog", filename.c_str());
|
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;
|
AST::sv_mode_but_global_and_used_for_literally_one_condition = parse_mode.sv;
|
||||||
std::string code_after_preproc;
|
std::string code_after_preproc;
|
||||||
|
|
||||||
|
|
|
@ -558,13 +558,16 @@ public:
|
||||||
int index;
|
int index;
|
||||||
const_iterator(const dict *ptr, int index) : ptr(ptr), index(index) { }
|
const_iterator(const dict *ptr, int index) : ptr(ptr), index(index) { }
|
||||||
public:
|
public:
|
||||||
typedef std::forward_iterator_tag iterator_category;
|
typedef std::bidirectional_iterator_tag iterator_category;
|
||||||
typedef std::pair<K, T> value_type;
|
typedef std::pair<K, T> value_type;
|
||||||
typedef ptrdiff_t difference_type;
|
typedef ptrdiff_t difference_type;
|
||||||
typedef std::pair<K, T>* pointer;
|
typedef const std::pair<K, T>* pointer;
|
||||||
typedef std::pair<K, T>& reference;
|
typedef const std::pair<K, T>& reference;
|
||||||
const_iterator() { }
|
const_iterator() { }
|
||||||
const_iterator operator++() { index--; return *this; }
|
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; }
|
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; }
|
||||||
bool operator==(const const_iterator &other) const { return index == other.index; }
|
bool operator==(const const_iterator &other) const { return index == other.index; }
|
||||||
|
@ -598,6 +601,13 @@ public:
|
||||||
const std::pair<K, T> *operator->() const { return &ptr->entries[index].udata; }
|
const std::pair<K, T> *operator->() const { return &ptr->entries[index].udata; }
|
||||||
operator const_iterator() const { return const_iterator(ptr, index); }
|
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()
|
constexpr dict()
|
||||||
{
|
{
|
||||||
|
@ -847,7 +857,7 @@ public:
|
||||||
|
|
||||||
const_iterator begin() const { return const_iterator(this, int(entries.size())-1); }
|
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 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>
|
template<typename K, typename OPS>
|
||||||
|
|
|
@ -5855,6 +5855,7 @@ RTLIL::CaseRule *RTLIL::CaseRule::clone() const
|
||||||
RTLIL::CaseRule *new_caserule = new RTLIL::CaseRule;
|
RTLIL::CaseRule *new_caserule = new RTLIL::CaseRule;
|
||||||
new_caserule->compare = compare;
|
new_caserule->compare = compare;
|
||||||
new_caserule->actions = actions;
|
new_caserule->actions = actions;
|
||||||
|
new_caserule->attributes = attributes;
|
||||||
for (auto &it : switches)
|
for (auto &it : switches)
|
||||||
new_caserule->switches.push_back(it->clone());
|
new_caserule->switches.push_back(it->clone());
|
||||||
return new_caserule;
|
return new_caserule;
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
// do not depend on any other components of yosys (except stuff like log_*).
|
// do not depend on any other components of yosys (except stuff like log_*).
|
||||||
|
|
||||||
#include "kernel/yosys.h"
|
#include "kernel/yosys.h"
|
||||||
|
#include <iterator>
|
||||||
|
|
||||||
#ifndef UTILS_H
|
#ifndef UTILS_H
|
||||||
#define UTILS_H
|
#define UTILS_H
|
||||||
|
@ -276,6 +277,16 @@ inline int ceil_log2(int x)
|
||||||
#endif
|
#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
|
YOSYS_NAMESPACE_END
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -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)
|
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";
|
string bugpoint_file = "bugpoint-case";
|
||||||
if (suffix.size())
|
if (suffix.size())
|
||||||
bugpoint_file += stringf(".%.8s", suffix.c_str());
|
bugpoint_file += stringf(".%.8s", suffix.c_str());
|
||||||
|
|
|
@ -1031,6 +1031,10 @@ struct TechmapPass : public Pass {
|
||||||
log(" -dont_map <celltype>\n");
|
log(" -dont_map <celltype>\n");
|
||||||
log(" leave the given cell type unmapped by ignoring any mapping rules for it\n");
|
log(" leave the given cell type unmapped by ignoring any mapping rules for it\n");
|
||||||
log("\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("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("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");
|
log("the module name will be used to match the cell. Multiple space-separated cell\n");
|
||||||
|
@ -1184,6 +1188,11 @@ struct TechmapPass : public Pass {
|
||||||
verilog_frontend += " -I " + args[++argidx];
|
verilog_frontend += " -I " + args[++argidx];
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (args[argidx] == "-relativeshare") {
|
||||||
|
verilog_frontend += " -relativeshare";
|
||||||
|
log_experimental("techmap -relativeshare");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (args[argidx] == "-assert") {
|
if (args[argidx] == "-assert") {
|
||||||
worker.assert_mode = true;
|
worker.assert_mode = true;
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -98,13 +98,17 @@ struct SynthPass : public ScriptPass {
|
||||||
log(" mapping library in the `techmap` step. this option can be\n");
|
log(" mapping library in the `techmap` step. this option can be\n");
|
||||||
log(" repeated.\n");
|
log(" repeated.\n");
|
||||||
log("\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");
|
log("The following commands are executed by this synthesis command:\n");
|
||||||
help_script();
|
help_script();
|
||||||
log("\n");
|
log("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
string top_module, fsm_opts, memory_opts, abc;
|
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;
|
int lut;
|
||||||
std::vector<std::string> techmap_maps;
|
std::vector<std::string> techmap_maps;
|
||||||
|
|
||||||
|
@ -124,6 +128,7 @@ struct SynthPass : public ScriptPass {
|
||||||
flowmap = false;
|
flowmap = false;
|
||||||
booth = false;
|
booth = false;
|
||||||
hieropt = false;
|
hieropt = false;
|
||||||
|
relative_share = false;
|
||||||
abc = "abc";
|
abc = "abc";
|
||||||
techmap_maps.clear();
|
techmap_maps.clear();
|
||||||
}
|
}
|
||||||
|
@ -211,6 +216,11 @@ struct SynthPass : public ScriptPass {
|
||||||
hieropt = true;
|
hieropt = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (args[argidx] == "-relativeshare") {
|
||||||
|
relative_share = true;
|
||||||
|
log_experimental("synth -relativeshare");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
extra_args(args, argidx, design);
|
extra_args(args, argidx, design);
|
||||||
|
@ -239,6 +249,10 @@ struct SynthPass : public ScriptPass {
|
||||||
else
|
else
|
||||||
hieropt_flag = hieropt ? " -hier" : "";
|
hieropt_flag = hieropt ? " -hier" : "";
|
||||||
|
|
||||||
|
std::string techmap_cmd = "techmap";
|
||||||
|
if (relative_share)
|
||||||
|
techmap_cmd += " -relativeshare";
|
||||||
|
|
||||||
if (check_label("begin")) {
|
if (check_label("begin")) {
|
||||||
if (help_mode) {
|
if (help_mode) {
|
||||||
run("hierarchy -check [-top <top> | -auto-top]");
|
run("hierarchy -check [-top <top> | -auto-top]");
|
||||||
|
@ -268,9 +282,9 @@ struct SynthPass : public ScriptPass {
|
||||||
run("peepopt");
|
run("peepopt");
|
||||||
run("opt_clean");
|
run("opt_clean");
|
||||||
if (help_mode)
|
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)
|
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)
|
if (booth || help_mode)
|
||||||
run("booth", " (if -booth)");
|
run("booth", " (if -booth)");
|
||||||
if (!noalumacc)
|
if (!noalumacc)
|
||||||
|
@ -287,22 +301,22 @@ struct SynthPass : public ScriptPass {
|
||||||
run("memory_map");
|
run("memory_map");
|
||||||
run("opt -full");
|
run("opt -full");
|
||||||
if (help_mode) {
|
if (help_mode) {
|
||||||
run("techmap", " (unless -extra-map)");
|
run(techmap_cmd, " (unless -extra-map)");
|
||||||
run("techmap -map +/techmap.v -map <inject>", " (if -extra-map)");
|
run(techmap_cmd + " -map +/techmap.v -map <inject>", " (if -extra-map)");
|
||||||
} else {
|
} else {
|
||||||
std::string techmap_opts;
|
std::string techmap_opts;
|
||||||
if (!techmap_maps.empty())
|
if (!techmap_maps.empty())
|
||||||
techmap_opts += " -map +/techmap.v";
|
techmap_opts += " -map +/techmap.v";
|
||||||
for (auto fn : techmap_maps)
|
for (auto fn : techmap_maps)
|
||||||
techmap_opts += stringf(" -map %s", fn.c_str());
|
techmap_opts += stringf(" -map %s", fn.c_str());
|
||||||
run("techmap" + techmap_opts);
|
run(techmap_cmd + techmap_opts);
|
||||||
}
|
}
|
||||||
if (help_mode) {
|
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("clean; opt_lut", " (if -noabc and -lut)");
|
||||||
run("flowmap -maxlut K", " (if -flowmap and -lut)");
|
run("flowmap -maxlut K", " (if -flowmap and -lut)");
|
||||||
} else if (noabc && 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");
|
run("clean; opt_lut");
|
||||||
} else if (flowmap) {
|
} else if (flowmap) {
|
||||||
run(stringf("flowmap -maxlut %d", lut));
|
run(stringf("flowmap -maxlut %d", lut));
|
||||||
|
|
|
@ -69,7 +69,7 @@ struct SynthPass : public ScriptPass
|
||||||
log(" use the specified Verilog file for extra primitives (can be specified multiple\n");
|
log(" use the specified Verilog file for extra primitives (can be specified multiple\n");
|
||||||
log(" times).\n");
|
log(" times).\n");
|
||||||
log("\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(" use the specified Verilog file for extra techmap rules (can be specified multiple\n");
|
||||||
log(" times).\n");
|
log(" times).\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
|
|
|
@ -22,34 +22,37 @@ logger -check-expected
|
||||||
|
|
||||||
# raise_error with int exits with status
|
# raise_error with int exits with status
|
||||||
design -load read
|
design -load read
|
||||||
|
setattr -mod -unset raise_error def other
|
||||||
|
dump
|
||||||
bugpoint -suffix error -yosys ../../yosys -command raise_error -expect-return 7
|
bugpoint -suffix error -yosys ../../yosys -command raise_error -expect-return 7
|
||||||
select -assert-mod-count 1 =*
|
select -assert-mod-count 1 =*
|
||||||
select -assert-mod-count 1 top
|
select -assert-mod-count 1 top
|
||||||
|
|
||||||
# raise_error -always still uses 'raise_error' attribute if possible
|
# raise_error -always still uses 'raise_error' attribute if possible
|
||||||
design -load read
|
design -load read
|
||||||
|
setattr -mod -unset raise_error def other
|
||||||
bugpoint -suffix error -yosys ../../yosys -command "raise_error -always" -expect-return 7
|
bugpoint -suffix error -yosys ../../yosys -command "raise_error -always" -expect-return 7
|
||||||
select -assert-mod-count 1 =*
|
select -assert-mod-count 1 =*
|
||||||
select -assert-mod-count 1 top
|
select -assert-mod-count 1 top
|
||||||
|
|
||||||
# raise_error with string prints message and exits with 1
|
# raise_error with string prints message and exits with 1
|
||||||
design -load read
|
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
|
bugpoint -suffix error -yosys ../../yosys -command raise_error -grep "help me" -expect-return 1
|
||||||
select -assert-mod-count 1 =*
|
select -assert-mod-count 1 =*
|
||||||
select -assert-mod-count 1 other
|
select -assert-mod-count 1 other
|
||||||
|
|
||||||
# raise_error with no value exits with 1
|
# raise_error with no value exits with 1
|
||||||
design -load read
|
design -load read
|
||||||
rename def zzy
|
setattr -mod -unset raise_error top
|
||||||
delete other
|
delete other
|
||||||
bugpoint -suffix error -yosys ../../yosys -command raise_error -expect-return 1
|
bugpoint -suffix error -yosys ../../yosys -command raise_error -expect-return 1
|
||||||
select -assert-mod-count 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
|
# raise_error -stderr prints to stderr and exits with 1
|
||||||
design -load read
|
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
|
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 =*
|
||||||
select -assert-mod-count 1 other
|
select -assert-mod-count 1 other
|
||||||
|
|
|
@ -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)])
|
run(['g++', '-g', '-std=c++17'] + args + [str(in_path), '-o', str(out_path)])
|
||||||
|
|
||||||
def yosys_synth(verilog_file, rtlil_file):
|
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
|
# 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 = ""):
|
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'
|
tb_file = base_path / 'tests/functional/picorv32_tb.v'
|
||||||
cpu_file = base_path / 'tests/functional/picorv32.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
|
# 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
1
tests/rtlil/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
/temp
|
40
tests/rtlil/everything.v
Normal file
40
tests/rtlil/everything.v
Normal 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
|
10
tests/rtlil/roundtrip-design.sh
Normal file
10
tests/rtlil/roundtrip-design.sh
Normal 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
|
283
tests/rtlil/roundtrip-text.ref.il
Normal file
283
tests/rtlil/roundtrip-text.ref.il
Normal file
|
@ -0,0 +1,283 @@
|
||||||
|
autoidx 15
|
||||||
|
attribute \src "everything.v:1.1-32.10"
|
||||||
|
attribute \cells_not_processed 1
|
||||||
|
module \alu
|
||||||
|
attribute \src "everything.v:2.8-2.11"
|
||||||
|
wire input 1 \clk
|
||||||
|
attribute \src "everything.v:3.14-3.15"
|
||||||
|
wire width 8 input 2 \A
|
||||||
|
attribute \src "everything.v:4.14-4.15"
|
||||||
|
wire width 8 input 3 \B
|
||||||
|
attribute \src "everything.v:5.14-5.23"
|
||||||
|
wire width 4 input 4 \operation
|
||||||
|
attribute \src "everything.v:6.19-6.25"
|
||||||
|
wire width 8 output 5 \result
|
||||||
|
attribute \src "everything.v:7.13-7.15"
|
||||||
|
wire output 6 \CF
|
||||||
|
attribute \src "everything.v:8.13-8.15"
|
||||||
|
wire output 7 \ZF
|
||||||
|
attribute \src "everything.v:9.13-9.15"
|
||||||
|
wire output 8 \SF
|
||||||
|
attribute \src "everything.v:15.12-15.15"
|
||||||
|
wire width 9 \tmp
|
||||||
|
attribute \src "everything.v:17.2-31.5"
|
||||||
|
wire width 8 $0\result[7:0]
|
||||||
|
attribute \src "everything.v:17.2-31.5"
|
||||||
|
wire $0\CF[0:0]
|
||||||
|
attribute \src "everything.v:17.2-31.5"
|
||||||
|
wire $0\ZF[0:0]
|
||||||
|
attribute \src "everything.v:17.2-31.5"
|
||||||
|
wire $0\SF[0:0]
|
||||||
|
attribute \src "everything.v:17.2-31.5"
|
||||||
|
wire width 9 $0\tmp[8:0]
|
||||||
|
attribute \src "everything.v:17.2-31.5"
|
||||||
|
wire width 9 $1\tmp[8:0]
|
||||||
|
attribute \src "everything.v:21.11-21.16"
|
||||||
|
wire width 9 $add$everything.v:21$2_Y
|
||||||
|
attribute \src "everything.v:23.11-23.16"
|
||||||
|
wire width 9 $sub$everything.v:23$3_Y
|
||||||
|
attribute \src "everything.v:27.9-27.22"
|
||||||
|
wire $eq$everything.v:27$4_Y
|
||||||
|
attribute \src "everything.v:21.11-21.16"
|
||||||
|
cell $add $add$everything.v:21$2
|
||||||
|
parameter \A_SIGNED 0
|
||||||
|
parameter \B_SIGNED 0
|
||||||
|
parameter \A_WIDTH 8
|
||||||
|
parameter \B_WIDTH 8
|
||||||
|
parameter \Y_WIDTH 9
|
||||||
|
connect \A \A
|
||||||
|
connect \B \B
|
||||||
|
connect \Y $add$everything.v:21$2_Y
|
||||||
|
end
|
||||||
|
attribute \src "everything.v:23.11-23.16"
|
||||||
|
cell $sub $sub$everything.v:23$3
|
||||||
|
parameter \A_SIGNED 0
|
||||||
|
parameter \B_SIGNED 0
|
||||||
|
parameter \A_WIDTH 8
|
||||||
|
parameter \B_WIDTH 8
|
||||||
|
parameter \Y_WIDTH 9
|
||||||
|
connect \A \A
|
||||||
|
connect \B \B
|
||||||
|
connect \Y $sub$everything.v:23$3_Y
|
||||||
|
end
|
||||||
|
attribute \src "everything.v:27.9-27.22"
|
||||||
|
cell $eq $eq$everything.v:27$4
|
||||||
|
parameter \A_SIGNED 0
|
||||||
|
parameter \B_SIGNED 0
|
||||||
|
parameter \A_WIDTH 8
|
||||||
|
parameter \B_WIDTH 32
|
||||||
|
parameter \Y_WIDTH 1
|
||||||
|
connect \A $1\tmp[8:0] [7:0]
|
||||||
|
connect \B 0
|
||||||
|
connect \Y $eq$everything.v:27$4_Y
|
||||||
|
end
|
||||||
|
attribute \src "everything.v:17.2-31.5"
|
||||||
|
process $proc$everything.v:17$1
|
||||||
|
assign { } { }
|
||||||
|
assign { } { }
|
||||||
|
assign { } { }
|
||||||
|
assign { } { }
|
||||||
|
assign { } { }
|
||||||
|
assign $0\tmp[8:0] $1\tmp[8:0]
|
||||||
|
assign $0\CF[0:0] $1\tmp[8:0] [8]
|
||||||
|
assign $0\ZF[0:0] $eq$everything.v:27$4_Y
|
||||||
|
assign $0\SF[0:0] $1\tmp[8:0] [7]
|
||||||
|
assign $0\result[7:0] $1\tmp[8:0] [7:0]
|
||||||
|
attribute \src "everything.v:19.3-24.10"
|
||||||
|
switch \operation
|
||||||
|
attribute \src "everything.v:19.19-19.19"
|
||||||
|
case 4'0000
|
||||||
|
assign { } { }
|
||||||
|
assign $1\tmp[8:0] $add$everything.v:21$2_Y
|
||||||
|
attribute \src "everything.v:21.17-21.17"
|
||||||
|
case 4'0001
|
||||||
|
assign { } { }
|
||||||
|
assign $1\tmp[8:0] $sub$everything.v:23$3_Y
|
||||||
|
case
|
||||||
|
assign $1\tmp[8:0] \tmp
|
||||||
|
end
|
||||||
|
sync posedge \clk
|
||||||
|
update \result $0\result[7:0]
|
||||||
|
update \CF $0\CF[0:0]
|
||||||
|
update \ZF $0\ZF[0:0]
|
||||||
|
update \SF $0\SF[0:0]
|
||||||
|
update \tmp $0\tmp[8:0]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
attribute \src "everything.v:34.1-40.10"
|
||||||
|
attribute \cells_not_processed 1
|
||||||
|
module \foo
|
||||||
|
attribute \src "everything.v:35.17-35.18"
|
||||||
|
wire width 8 input 1 \a
|
||||||
|
attribute \src "everything.v:35.32-35.33"
|
||||||
|
wire width 8 input 2 \b
|
||||||
|
attribute \src "everything.v:35.48-35.49"
|
||||||
|
wire width 8 output 3 \y
|
||||||
|
attribute \src "everything.v:37.16-37.18"
|
||||||
|
wire width 8 \bb
|
||||||
|
attribute \src "everything.v:39.16-39.22"
|
||||||
|
wire width 8 $add$everything.v:39$5_Y
|
||||||
|
attribute \src "everything.v:39.16-39.22"
|
||||||
|
cell $add $add$everything.v:39$5
|
||||||
|
parameter \A_SIGNED 0
|
||||||
|
parameter \B_SIGNED 0
|
||||||
|
parameter \A_WIDTH 8
|
||||||
|
parameter \B_WIDTH 8
|
||||||
|
parameter \Y_WIDTH 8
|
||||||
|
connect \A \a
|
||||||
|
connect \B \bb
|
||||||
|
connect \Y $add$everything.v:39$5_Y
|
||||||
|
end
|
||||||
|
connect \b \bb
|
||||||
|
connect \y $add$everything.v:39$5_Y
|
||||||
|
end
|
||||||
|
attribute \cells_not_processed 1
|
||||||
|
attribute \src "everything.v:1.1-32.10"
|
||||||
|
module \zzz
|
||||||
|
attribute \src "everything.v:27.9-27.22"
|
||||||
|
wire $eq$everything.v:27$4_Y
|
||||||
|
attribute \src "everything.v:23.11-23.16"
|
||||||
|
wire width 9 $sub$everything.v:23$3_Y
|
||||||
|
attribute \src "everything.v:21.11-21.16"
|
||||||
|
wire width 9 $add$everything.v:21$2_Y
|
||||||
|
attribute \src "everything.v:17.2-31.5"
|
||||||
|
wire width 9 $1\tmp[8:0]
|
||||||
|
attribute \src "everything.v:17.2-31.5"
|
||||||
|
wire width 9 $0\tmp[8:0]
|
||||||
|
attribute \src "everything.v:17.2-31.5"
|
||||||
|
wire $0\SF[0:0]
|
||||||
|
attribute \src "everything.v:17.2-31.5"
|
||||||
|
wire $0\ZF[0:0]
|
||||||
|
attribute \src "everything.v:17.2-31.5"
|
||||||
|
wire $0\CF[0:0]
|
||||||
|
attribute \src "everything.v:17.2-31.5"
|
||||||
|
wire width 8 $0\result[7:0]
|
||||||
|
attribute \src "everything.v:15.12-15.15"
|
||||||
|
wire width 9 \tmp
|
||||||
|
attribute \src "everything.v:9.13-9.15"
|
||||||
|
wire output 8 \SF
|
||||||
|
attribute \src "everything.v:8.13-8.15"
|
||||||
|
wire output 7 \ZF
|
||||||
|
attribute \src "everything.v:7.13-7.15"
|
||||||
|
wire output 6 \CF
|
||||||
|
attribute \src "everything.v:6.19-6.25"
|
||||||
|
wire width 8 output 5 \result
|
||||||
|
attribute \src "everything.v:5.14-5.23"
|
||||||
|
wire width 4 input 4 \operation
|
||||||
|
attribute \src "everything.v:4.14-4.15"
|
||||||
|
wire width 8 input 3 \B
|
||||||
|
attribute \src "everything.v:3.14-3.15"
|
||||||
|
wire width 8 input 2 \A
|
||||||
|
attribute \src "everything.v:2.8-2.11"
|
||||||
|
wire input 1 \clk
|
||||||
|
wire $procmux$8_CMP
|
||||||
|
wire width 9 $procmux$7_Y
|
||||||
|
wire $procmux$9_CMP
|
||||||
|
attribute \src "everything.v:27.9-27.22"
|
||||||
|
cell $logic_not $eq$everything.v:27$4
|
||||||
|
parameter \A_SIGNED 0
|
||||||
|
parameter \Y_WIDTH 1
|
||||||
|
parameter \A_WIDTH 8
|
||||||
|
connect \A $1\tmp[8:0] [7:0]
|
||||||
|
connect \Y $eq$everything.v:27$4_Y
|
||||||
|
end
|
||||||
|
attribute \src "everything.v:23.11-23.16"
|
||||||
|
cell $sub $sub$everything.v:23$3
|
||||||
|
parameter \A_SIGNED 0
|
||||||
|
parameter \B_SIGNED 0
|
||||||
|
parameter \A_WIDTH 8
|
||||||
|
parameter \B_WIDTH 8
|
||||||
|
parameter \Y_WIDTH 9
|
||||||
|
connect \A \A
|
||||||
|
connect \B \B
|
||||||
|
connect \Y $sub$everything.v:23$3_Y
|
||||||
|
end
|
||||||
|
attribute \src "everything.v:21.11-21.16"
|
||||||
|
cell $add $add$everything.v:21$2
|
||||||
|
parameter \A_SIGNED 0
|
||||||
|
parameter \B_SIGNED 0
|
||||||
|
parameter \A_WIDTH 8
|
||||||
|
parameter \B_WIDTH 8
|
||||||
|
parameter \Y_WIDTH 9
|
||||||
|
connect \A \A
|
||||||
|
connect \B \B
|
||||||
|
connect \Y $add$everything.v:21$2_Y
|
||||||
|
end
|
||||||
|
attribute \src "everything.v:21.17-21.17|everything.v:19.3-24.10"
|
||||||
|
attribute \full_case 1
|
||||||
|
cell $eq $procmux$8_CMP0
|
||||||
|
parameter \A_SIGNED 0
|
||||||
|
parameter \B_SIGNED 0
|
||||||
|
parameter \A_WIDTH 4
|
||||||
|
parameter \B_WIDTH 4
|
||||||
|
parameter \Y_WIDTH 1
|
||||||
|
connect \A \operation
|
||||||
|
connect \B 4'0001
|
||||||
|
connect \Y $procmux$8_CMP
|
||||||
|
end
|
||||||
|
attribute \src "everything.v:21.17-21.17|everything.v:19.3-24.10"
|
||||||
|
attribute \full_case 1
|
||||||
|
cell $pmux $procmux$7
|
||||||
|
parameter \WIDTH 9
|
||||||
|
parameter \S_WIDTH 2
|
||||||
|
connect \A \tmp
|
||||||
|
connect \B { $add$everything.v:21$2_Y $sub$everything.v:23$3_Y }
|
||||||
|
connect \S { $procmux$9_CMP $procmux$8_CMP }
|
||||||
|
connect \Y $procmux$7_Y
|
||||||
|
end
|
||||||
|
attribute \src "everything.v:19.19-19.19|everything.v:19.3-24.10"
|
||||||
|
attribute \full_case 1
|
||||||
|
cell $logic_not $procmux$9_CMP0
|
||||||
|
parameter \A_SIGNED 0
|
||||||
|
parameter \Y_WIDTH 1
|
||||||
|
parameter \A_WIDTH 4
|
||||||
|
connect \A \operation
|
||||||
|
connect \Y $procmux$9_CMP
|
||||||
|
end
|
||||||
|
attribute \src "everything.v:17.2-31.5"
|
||||||
|
cell $dff $procdff$10
|
||||||
|
parameter \WIDTH 8
|
||||||
|
parameter \CLK_POLARITY 1'1
|
||||||
|
connect \D $procmux$7_Y [7:0]
|
||||||
|
connect \Q \result
|
||||||
|
connect \CLK \clk
|
||||||
|
end
|
||||||
|
attribute \src "everything.v:17.2-31.5"
|
||||||
|
cell $dff $procdff$11
|
||||||
|
parameter \WIDTH 1
|
||||||
|
parameter \CLK_POLARITY 1'1
|
||||||
|
connect \D $procmux$7_Y [8]
|
||||||
|
connect \Q \CF
|
||||||
|
connect \CLK \clk
|
||||||
|
end
|
||||||
|
attribute \src "everything.v:17.2-31.5"
|
||||||
|
cell $dff $procdff$12
|
||||||
|
parameter \WIDTH 1
|
||||||
|
parameter \CLK_POLARITY 1'1
|
||||||
|
connect \D $eq$everything.v:27$4_Y
|
||||||
|
connect \Q \ZF
|
||||||
|
connect \CLK \clk
|
||||||
|
end
|
||||||
|
attribute \src "everything.v:17.2-31.5"
|
||||||
|
cell $dff $procdff$13
|
||||||
|
parameter \WIDTH 1
|
||||||
|
parameter \CLK_POLARITY 1'1
|
||||||
|
connect \D $procmux$7_Y [7]
|
||||||
|
connect \Q \SF
|
||||||
|
connect \CLK \clk
|
||||||
|
end
|
||||||
|
attribute \src "everything.v:17.2-31.5"
|
||||||
|
cell $dff $procdff$14
|
||||||
|
parameter \WIDTH 9
|
||||||
|
parameter \CLK_POLARITY 1'1
|
||||||
|
connect \D $procmux$7_Y
|
||||||
|
connect \Q \tmp
|
||||||
|
connect \CLK \clk
|
||||||
|
end
|
||||||
|
connect $0\result[7:0] $1\tmp[8:0] [7:0]
|
||||||
|
connect $0\SF[0:0] $1\tmp[8:0] [7]
|
||||||
|
connect $0\ZF[0:0] $eq$everything.v:27$4_Y
|
||||||
|
connect $0\CF[0:0] $1\tmp[8:0] [8]
|
||||||
|
connect $0\tmp[8:0] $1\tmp[8:0]
|
||||||
|
connect $1\tmp[8:0] $procmux$7_Y
|
||||||
|
end
|
39
tests/rtlil/roundtrip-text.sh
Normal file
39
tests/rtlil/roundtrip-text.sh
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
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
|
||||||
|
diff temp/roundtrip-text.dump.il roundtrip-text.ref.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
|
||||||
|
|
||||||
|
echo "Without ABC, we don't get any irreproducibility and can pin that"
|
||||||
|
echo "Has this test case started failing for you? Consider updating the reference"
|
||||||
|
$YS -p "read_verilog -sv everything.v; synth -relativeshare -noabc; write_rtlil temp/roundtrip-text.synth.il"
|
||||||
|
remove_empty_lines temp/roundtrip-text.synth.il
|
||||||
|
tail -n +2 temp/roundtrip-text.synth.il > temp/roundtrip-text.synth-nogen.il
|
||||||
|
diff temp/roundtrip-text.synth-nogen.il roundtrip-text.synth.ref.il
|
1194
tests/rtlil/roundtrip-text.synth.ref.il
Normal file
1194
tests/rtlil/roundtrip-text.synth.ref.il
Normal file
File diff suppressed because it is too large
Load diff
4
tests/rtlil/run-test.sh
Executable file
4
tests/rtlil/run-test.sh
Executable file
|
@ -0,0 +1,4 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -eu
|
||||||
|
source ../gen-tests-makefile.sh
|
||||||
|
generate_mk --bash
|
Loading…
Add table
Add a link
Reference in a new issue