mirror of https://github.com/YosysHQ/yosys.git
rtlil_frontend, rtlil_backend: dump statics as strings, comments for src
This commit is contained in:
parent
9cb838febe
commit
6f1ca02a90
|
|
@ -32,18 +32,19 @@ 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, const RTLIL::Design *design, bool resolve_src)
|
void RTLIL_BACKEND::dump_attributes(std::ostream &f, std::string indent, const RTLIL::AttrObject *obj, const RTLIL::Design *design, bool stringify)
|
||||||
{
|
{
|
||||||
// Emit the typed src field first. It is not stored in obj->attributes
|
// Emit the typed src field first. It is not stored in obj->attributes
|
||||||
// — the dict no longer holds ID::src under any circumstance. Backends
|
// — the dict no longer holds ID::src under any circumstance. Backends
|
||||||
// that want to materialize the pipe-joined literal pass resolve_src.
|
// that want to materialize the pipe-joined literal pass stringify.
|
||||||
if (design && design->obj_src_id(obj) != Twine::Null) {
|
if (design && design->obj_src_id(obj) != Twine::Null) {
|
||||||
TwineRef id = design->obj_src_id(obj);
|
TwineRef id = design->obj_src_id(obj);
|
||||||
f << stringf("%s" "attribute \\src ", indent);
|
f << stringf("%s" "attribute \\src ", indent);
|
||||||
if (resolve_src) {
|
if (stringify) {
|
||||||
dump_const(f, RTLIL::Const(design->twines.str(id)));
|
dump_const(f, RTLIL::Const(design->twines.str(id)));
|
||||||
} else {
|
} else {
|
||||||
dump_const(f, RTLIL::Const(stringf("@%zu", id)));
|
dump_const(f, RTLIL::Const(stringf("@%zu", id)));
|
||||||
|
f << stringf(" # %s", design->twines.str(id).c_str());
|
||||||
}
|
}
|
||||||
f << stringf("\n");
|
f << stringf("\n");
|
||||||
}
|
}
|
||||||
|
|
@ -59,7 +60,11 @@ void RTLIL_BACKEND::dump_twines(std::ostream &f, const RTLIL::Design *design)
|
||||||
if (!design || design->twines.size() == 0)
|
if (!design || design->twines.size() == 0)
|
||||||
return;
|
return;
|
||||||
f << stringf("twines\n");
|
f << stringf("twines\n");
|
||||||
for (TwineRef id = 0; id < STATIC_TWINE_END; id++) {
|
std::vector<TwineRef> ids;
|
||||||
|
for (auto it = design->twines.backing.begin(); it != design->twines.backing.end(); ++it)
|
||||||
|
ids.push_back(STATIC_TWINE_END + design->twines.backing.get_index(it));
|
||||||
|
std::sort(ids.begin(), ids.end());
|
||||||
|
for (TwineRef id : ids) {
|
||||||
const Twine &n = design->twines[id];
|
const Twine &n = design->twines[id];
|
||||||
if (n.is_leaf()) {
|
if (n.is_leaf()) {
|
||||||
f << stringf(" leaf %zu ", id);
|
f << stringf(" leaf %zu ", id);
|
||||||
|
|
@ -141,38 +146,60 @@ void RTLIL_BACKEND::dump_const(std::ostream &f, const RTLIL::Const &data, int wi
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RTLIL_BACKEND::dump_sigchunk(std::ostream &f, const RTLIL::SigChunk &chunk, bool autoint)
|
static std::string twine_handle(TwineRef ref)
|
||||||
|
{
|
||||||
|
return stringf("%s@%zu", twine_is_public(ref) ? "$pub" : "$priv", (size_t)twine_untag(ref));
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string twine_ref(const RTLIL::Design *design, TwineRef ref, bool stringify)
|
||||||
|
{
|
||||||
|
if (stringify || twine_untag(ref) < STATIC_TWINE_END)
|
||||||
|
return design->twines.str(ref);
|
||||||
|
return twine_handle(ref);
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string twine_cmt(const RTLIL::Design *design, TwineRef ref, bool stringify)
|
||||||
|
{
|
||||||
|
if (stringify || twine_untag(ref) < STATIC_TWINE_END)
|
||||||
|
return "";
|
||||||
|
return stringf(" # %s", design->twines.str(ref).c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void RTLIL_BACKEND::dump_sigchunk(std::ostream &f, const RTLIL::SigChunk &chunk, bool autoint, bool stringify)
|
||||||
{
|
{
|
||||||
if (chunk.wire == NULL) {
|
if (chunk.wire == NULL) {
|
||||||
dump_const(f, chunk.data, chunk.width, chunk.offset, autoint);
|
dump_const(f, chunk.data, chunk.width, chunk.offset, autoint);
|
||||||
} else {
|
} else {
|
||||||
|
TwineRef wref = chunk.wire->name.ref();
|
||||||
|
std::string name = (stringify || twine_untag(wref) < STATIC_TWINE_END)
|
||||||
|
? chunk.wire->name.str() : twine_handle(wref);
|
||||||
if (chunk.width == chunk.wire->width && chunk.offset == 0)
|
if (chunk.width == chunk.wire->width && chunk.offset == 0)
|
||||||
f << stringf("%s", chunk.wire->name);
|
f << name;
|
||||||
else if (chunk.width == 1)
|
else if (chunk.width == 1)
|
||||||
f << stringf("%s [%d]", chunk.wire->name, chunk.offset);
|
f << stringf("%s [%d]", name.c_str(), chunk.offset);
|
||||||
else
|
else
|
||||||
f << stringf("%s [%d:%d]", chunk.wire->name, chunk.offset+chunk.width-1, chunk.offset);
|
f << stringf("%s [%d:%d]", name.c_str(), chunk.offset+chunk.width-1, chunk.offset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RTLIL_BACKEND::dump_sigspec(std::ostream &f, const RTLIL::SigSpec &sig, bool autoint)
|
void RTLIL_BACKEND::dump_sigspec(std::ostream &f, const RTLIL::SigSpec &sig, bool autoint, bool stringify)
|
||||||
{
|
{
|
||||||
if (sig.is_chunk()) {
|
if (sig.is_chunk()) {
|
||||||
dump_sigchunk(f, sig.as_chunk(), autoint);
|
dump_sigchunk(f, sig.as_chunk(), autoint, stringify);
|
||||||
} else {
|
} else {
|
||||||
f << stringf("{ ");
|
f << stringf("{ ");
|
||||||
auto chunks = sig.chunks();
|
auto chunks = sig.chunks();
|
||||||
for (const auto& chunk : reversed(chunks)) {
|
for (const auto& chunk : reversed(chunks)) {
|
||||||
dump_sigchunk(f, chunk, false);
|
dump_sigchunk(f, chunk, false, stringify);
|
||||||
f << stringf(" ");
|
f << stringf(" ");
|
||||||
}
|
}
|
||||||
f << stringf("}");
|
f << stringf("}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RTLIL_BACKEND::dump_wire(std::ostream &f, std::string indent, const RTLIL::Wire *wire, const RTLIL::Design *design, bool resolve_src)
|
void RTLIL_BACKEND::dump_wire(std::ostream &f, std::string indent, const RTLIL::Wire *wire, const RTLIL::Design *design, bool stringify)
|
||||||
{
|
{
|
||||||
dump_attributes(f, indent, wire, design, resolve_src);
|
dump_attributes(f, indent, wire, design, stringify);
|
||||||
if (wire->driverCell_) {
|
if (wire->driverCell_) {
|
||||||
f << stringf("%s" "# driver %s %s\n", indent,
|
f << stringf("%s" "# driver %s %s\n", indent,
|
||||||
wire->driverCell()->name, wire->driverPort());
|
wire->driverCell()->name, wire->driverPort());
|
||||||
|
|
@ -192,12 +219,12 @@ void RTLIL_BACKEND::dump_wire(std::ostream &f, std::string indent, const RTLIL::
|
||||||
f << stringf("inout %d ", wire->port_id);
|
f << stringf("inout %d ", wire->port_id);
|
||||||
if (wire->is_signed)
|
if (wire->is_signed)
|
||||||
f << stringf("signed ");
|
f << stringf("signed ");
|
||||||
f << stringf("%s\n", wire->name);
|
f << twine_ref(design, wire->name.ref(), stringify) << twine_cmt(design, wire->name.ref(), stringify) << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
void RTLIL_BACKEND::dump_memory(std::ostream &f, std::string indent, const RTLIL::Memory *memory, const RTLIL::Design *design, bool resolve_src)
|
void RTLIL_BACKEND::dump_memory(std::ostream &f, std::string indent, const RTLIL::Memory *memory, const RTLIL::Design *design, bool stringify)
|
||||||
{
|
{
|
||||||
dump_attributes(f, indent, memory, design, resolve_src);
|
dump_attributes(f, indent, memory, design, stringify);
|
||||||
f << stringf("%s" "memory ", indent);
|
f << stringf("%s" "memory ", indent);
|
||||||
if (memory->width != 1)
|
if (memory->width != 1)
|
||||||
f << stringf("width %d ", memory->width);
|
f << stringf("width %d ", memory->width);
|
||||||
|
|
@ -205,13 +232,15 @@ void RTLIL_BACKEND::dump_memory(std::ostream &f, std::string indent, const RTLIL
|
||||||
f << stringf("size %d ", memory->size);
|
f << stringf("size %d ", memory->size);
|
||||||
if (memory->start_offset != 0)
|
if (memory->start_offset != 0)
|
||||||
f << stringf("offset %d ", memory->start_offset);
|
f << stringf("offset %d ", memory->start_offset);
|
||||||
f << stringf("%s\n", design->twines.str(memory->meta_->name).c_str());
|
f << twine_ref(design, memory->meta_->name, stringify) << twine_cmt(design, memory->meta_->name, stringify) << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
void RTLIL_BACKEND::dump_cell(std::ostream &f, std::string indent, const RTLIL::Cell *cell, const RTLIL::Design *design, bool resolve_src)
|
void RTLIL_BACKEND::dump_cell(std::ostream &f, std::string indent, const RTLIL::Cell *cell, const RTLIL::Design *design, bool stringify)
|
||||||
{
|
{
|
||||||
dump_attributes(f, indent, cell, design, resolve_src);
|
dump_attributes(f, indent, cell, design, stringify);
|
||||||
f << stringf("%s" "cell %s %s\n", indent, cell->type.str(), cell->name.str());
|
f << stringf("%s" "cell ", indent);
|
||||||
|
f << twine_ref(design, cell->type.ref(), stringify) << " " << twine_ref(design, cell->name.ref(), stringify)
|
||||||
|
<< twine_cmt(design, cell->type.ref(), stringify) << twine_cmt(design, cell->name.ref(), stringify) << "\n";
|
||||||
for (const auto& [name, param] : reversed(cell->parameters)) {
|
for (const auto& [name, param] : reversed(cell->parameters)) {
|
||||||
f << stringf("%s parameter%s%s%s %s ", indent,
|
f << stringf("%s parameter%s%s%s %s ", indent,
|
||||||
(param.flags & RTLIL::CONST_FLAG_SIGNED) != 0 ? " signed" : "",
|
(param.flags & RTLIL::CONST_FLAG_SIGNED) != 0 ? " signed" : "",
|
||||||
|
|
@ -222,53 +251,54 @@ void RTLIL_BACKEND::dump_cell(std::ostream &f, std::string indent, const RTLIL::
|
||||||
f << stringf("\n");
|
f << stringf("\n");
|
||||||
}
|
}
|
||||||
for (const auto& [port, sig] : reversed(cell->connections_)) {
|
for (const auto& [port, sig] : reversed(cell->connections_)) {
|
||||||
f << stringf("%s connect %s ", indent, design->twines.unescaped_str(port));
|
f << stringf("%s connect ", indent);
|
||||||
dump_sigspec(f, sig);
|
f << twine_ref(design, port, stringify) << " ";
|
||||||
f << stringf("\n");
|
dump_sigspec(f, sig, true, stringify);
|
||||||
|
f << twine_cmt(design, port, stringify) << "\n";
|
||||||
}
|
}
|
||||||
f << stringf("%s" "end\n", indent);
|
f << stringf("%s" "end\n", indent);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RTLIL_BACKEND::dump_proc_case_body(std::ostream &f, std::string indent, const RTLIL::CaseRule *cs, const RTLIL::Design *design, bool resolve_src)
|
void RTLIL_BACKEND::dump_proc_case_body(std::ostream &f, std::string indent, const RTLIL::CaseRule *cs, const RTLIL::Design *design, bool stringify)
|
||||||
{
|
{
|
||||||
for (const auto& [lhs, rhs] : cs->actions) {
|
for (const auto& [lhs, rhs] : cs->actions) {
|
||||||
f << stringf("%s" "assign ", indent);
|
f << stringf("%s" "assign ", indent);
|
||||||
dump_sigspec(f, lhs);
|
dump_sigspec(f, lhs, true, stringify);
|
||||||
f << stringf(" ");
|
f << stringf(" ");
|
||||||
dump_sigspec(f, rhs);
|
dump_sigspec(f, rhs, true, stringify);
|
||||||
f << stringf("\n");
|
f << stringf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto& sw : cs->switches)
|
for (const auto& sw : cs->switches)
|
||||||
dump_proc_switch(f, indent, sw, design, resolve_src);
|
dump_proc_switch(f, indent, sw, design, stringify);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RTLIL_BACKEND::dump_proc_switch(std::ostream &f, std::string indent, const RTLIL::SwitchRule *sw, const RTLIL::Design *design, bool resolve_src)
|
void RTLIL_BACKEND::dump_proc_switch(std::ostream &f, std::string indent, const RTLIL::SwitchRule *sw, const RTLIL::Design *design, bool stringify)
|
||||||
{
|
{
|
||||||
dump_attributes(f, indent, sw, design, resolve_src);
|
dump_attributes(f, indent, sw, design, stringify);
|
||||||
|
|
||||||
f << stringf("%s" "switch ", indent);
|
f << stringf("%s" "switch ", indent);
|
||||||
dump_sigspec(f, sw->signal);
|
dump_sigspec(f, sw->signal, true, stringify);
|
||||||
f << stringf("\n");
|
f << stringf("\n");
|
||||||
|
|
||||||
for (const auto case_ : sw->cases)
|
for (const auto case_ : sw->cases)
|
||||||
{
|
{
|
||||||
dump_attributes(f, indent, case_, design, resolve_src);
|
dump_attributes(f, indent, case_, design, stringify);
|
||||||
f << stringf("%s case ", indent);
|
f << stringf("%s case ", indent);
|
||||||
for (size_t i = 0; i < case_->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, case_->compare[i]);
|
dump_sigspec(f, case_->compare[i], true, stringify);
|
||||||
}
|
}
|
||||||
f << stringf("\n");
|
f << stringf("\n");
|
||||||
|
|
||||||
dump_proc_case_body(f, indent + " ", case_, design, resolve_src);
|
dump_proc_case_body(f, indent + " ", case_, design, stringify);
|
||||||
}
|
}
|
||||||
|
|
||||||
f << stringf("%s" "end\n", indent);
|
f << stringf("%s" "end\n", indent);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RTLIL_BACKEND::dump_proc_sync(std::ostream &f, std::string indent, const RTLIL::SyncRule *sy, const RTLIL::Design *design, bool resolve_src)
|
void RTLIL_BACKEND::dump_proc_sync(std::ostream &f, std::string indent, const RTLIL::SyncRule *sy, const RTLIL::Design *design, bool stringify)
|
||||||
{
|
{
|
||||||
f << stringf("%s" "sync ", indent);
|
f << stringf("%s" "sync ", indent);
|
||||||
switch (sy->type) {
|
switch (sy->type) {
|
||||||
|
|
@ -277,7 +307,7 @@ void RTLIL_BACKEND::dump_proc_sync(std::ostream &f, std::string indent, const RT
|
||||||
if (0) case RTLIL::STp: f << stringf("posedge ");
|
if (0) case RTLIL::STp: f << stringf("posedge ");
|
||||||
if (0) case RTLIL::STn: f << stringf("negedge ");
|
if (0) case RTLIL::STn: f << stringf("negedge ");
|
||||||
if (0) case RTLIL::STe: f << stringf("edge ");
|
if (0) case RTLIL::STe: f << stringf("edge ");
|
||||||
dump_sigspec(f, sy->signal);
|
dump_sigspec(f, sy->signal, true, stringify);
|
||||||
f << stringf("\n");
|
f << stringf("\n");
|
||||||
break;
|
break;
|
||||||
case RTLIL::STa: f << stringf("always\n"); break;
|
case RTLIL::STa: f << stringf("always\n"); break;
|
||||||
|
|
@ -287,55 +317,57 @@ void RTLIL_BACKEND::dump_proc_sync(std::ostream &f, std::string indent, const RT
|
||||||
|
|
||||||
for (const auto& [lhs, rhs] : sy->actions) {
|
for (const auto& [lhs, rhs] : sy->actions) {
|
||||||
f << stringf("%s update ", indent);
|
f << stringf("%s update ", indent);
|
||||||
dump_sigspec(f, lhs);
|
dump_sigspec(f, lhs, true, stringify);
|
||||||
f << stringf(" ");
|
f << stringf(" ");
|
||||||
dump_sigspec(f, rhs);
|
dump_sigspec(f, rhs, true, stringify);
|
||||||
f << stringf("\n");
|
f << stringf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto &it: sy->mem_write_actions) {
|
for (auto &it: sy->mem_write_actions) {
|
||||||
dump_attributes(f, indent, &it, design, resolve_src);
|
dump_attributes(f, indent, &it, design, stringify);
|
||||||
f << stringf("%s memwr %s ", indent, it.memid);
|
f << stringf("%s memwr %s ", indent, it.memid);
|
||||||
dump_sigspec(f, it.address);
|
dump_sigspec(f, it.address, true, stringify);
|
||||||
f << stringf(" ");
|
f << stringf(" ");
|
||||||
dump_sigspec(f, it.data);
|
dump_sigspec(f, it.data, true, stringify);
|
||||||
f << stringf(" ");
|
f << stringf(" ");
|
||||||
dump_sigspec(f, it.enable);
|
dump_sigspec(f, it.enable, true, stringify);
|
||||||
f << stringf(" ");
|
f << stringf(" ");
|
||||||
dump_const(f, it.priority_mask);
|
dump_const(f, it.priority_mask);
|
||||||
f << stringf("\n");
|
f << stringf("\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RTLIL_BACKEND::dump_proc(std::ostream &f, std::string indent, const RTLIL::Process *proc, const RTLIL::Design *design, bool resolve_src)
|
void RTLIL_BACKEND::dump_proc(std::ostream &f, std::string indent, const RTLIL::Process *proc, const RTLIL::Design *design, bool stringify)
|
||||||
{
|
{
|
||||||
dump_attributes(f, indent, proc, design, resolve_src);
|
dump_attributes(f, indent, proc, design, stringify);
|
||||||
f << stringf("%s" "process %s\n", indent, design->twines.str(proc->meta_->name).c_str());
|
f << stringf("%s" "process ", indent);
|
||||||
dump_proc_case_body(f, indent + " ", &proc->root_case, design, resolve_src);
|
f << twine_ref(design, proc->meta_->name, stringify) << twine_cmt(design, proc->meta_->name, stringify) << "\n";
|
||||||
|
dump_proc_case_body(f, indent + " ", &proc->root_case, design, stringify);
|
||||||
for (auto* sync : proc->syncs)
|
for (auto* sync : proc->syncs)
|
||||||
dump_proc_sync(f, indent + " ", sync, design, resolve_src);
|
dump_proc_sync(f, indent + " ", sync, design, stringify);
|
||||||
f << stringf("%s" "end\n", indent);
|
f << stringf("%s" "end\n", indent);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RTLIL_BACKEND::dump_conn(std::ostream &f, std::string indent, const RTLIL::SigSpec &left, const RTLIL::SigSpec &right)
|
void RTLIL_BACKEND::dump_conn(std::ostream &f, std::string indent, const RTLIL::SigSpec &left, const RTLIL::SigSpec &right, bool stringify)
|
||||||
{
|
{
|
||||||
f << stringf("%s" "connect ", indent);
|
f << stringf("%s" "connect ", indent);
|
||||||
dump_sigspec(f, left);
|
dump_sigspec(f, left, true, stringify);
|
||||||
f << stringf(" ");
|
f << stringf(" ");
|
||||||
dump_sigspec(f, right);
|
dump_sigspec(f, right, true, stringify);
|
||||||
f << stringf("\n");
|
f << stringf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void RTLIL_BACKEND::dump_module(std::ostream &f, std::string indent, RTLIL::Module *module, RTLIL::Design *design, bool only_selected, bool flag_m, bool flag_n, bool resolve_src)
|
void RTLIL_BACKEND::dump_module(std::ostream &f, std::string indent, RTLIL::Module *module, RTLIL::Design *design, bool only_selected, bool flag_m, bool flag_n, bool stringify)
|
||||||
{
|
{
|
||||||
bool print_header = flag_m || module->is_selected_whole();
|
bool print_header = flag_m || module->is_selected_whole();
|
||||||
bool print_body = !flag_n || !module->is_selected_whole();
|
bool print_body = !flag_n || !module->is_selected_whole();
|
||||||
|
|
||||||
if (print_header)
|
if (print_header)
|
||||||
{
|
{
|
||||||
dump_attributes(f, indent, module, design, resolve_src);
|
dump_attributes(f, indent, module, design, stringify);
|
||||||
|
|
||||||
f << stringf("%s" "module %s\n", indent, design->twines.str(module->meta_->name).c_str());
|
f << stringf("%s" "module ", indent);
|
||||||
|
f << twine_ref(design, module->meta_->name, stringify) << twine_cmt(design, module->meta_->name, stringify) << "\n";
|
||||||
|
|
||||||
if (!module->avail_parameters.empty()) {
|
if (!module->avail_parameters.empty()) {
|
||||||
if (only_selected)
|
if (only_selected)
|
||||||
|
|
@ -359,28 +391,28 @@ void RTLIL_BACKEND::dump_module(std::ostream &f, std::string indent, RTLIL::Modu
|
||||||
if (!only_selected || design->selected(module, wire)) {
|
if (!only_selected || design->selected(module, wire)) {
|
||||||
if (only_selected)
|
if (only_selected)
|
||||||
f << stringf("\n");
|
f << stringf("\n");
|
||||||
dump_wire(f, indent + " ", wire, design, resolve_src);
|
dump_wire(f, indent + " ", wire, design, stringify);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto& [_, mem] : reversed(module->memories))
|
for (const auto& [_, mem] : reversed(module->memories))
|
||||||
if (!only_selected || design->selected(module, mem)) {
|
if (!only_selected || design->selected(module, mem)) {
|
||||||
if (only_selected)
|
if (only_selected)
|
||||||
f << stringf("\n");
|
f << stringf("\n");
|
||||||
dump_memory(f, indent + " ", mem, design, resolve_src);
|
dump_memory(f, indent + " ", mem, design, stringify);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto& [_, cell] : reversed(module->cells_))
|
for (const auto& [_, cell] : reversed(module->cells_))
|
||||||
if (!only_selected || design->selected(module, cell)) {
|
if (!only_selected || design->selected(module, cell)) {
|
||||||
if (only_selected)
|
if (only_selected)
|
||||||
f << stringf("\n");
|
f << stringf("\n");
|
||||||
dump_cell(f, indent + " ", cell, design, resolve_src);
|
dump_cell(f, indent + " ", cell, design, stringify);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto& [_, process] : reversed(module->processes))
|
for (const auto& [_, process] : reversed(module->processes))
|
||||||
if (!only_selected || design->selected(module, process)) {
|
if (!only_selected || design->selected(module, process)) {
|
||||||
if (only_selected)
|
if (only_selected)
|
||||||
f << stringf("\n");
|
f << stringf("\n");
|
||||||
dump_proc(f, indent + " ", process, design, resolve_src);
|
dump_proc(f, indent + " ", process, design, stringify);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool first_conn_line = true;
|
bool first_conn_line = true;
|
||||||
|
|
@ -398,7 +430,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 + " ", lhs, rhs);
|
dump_conn(f, indent + " ", lhs, rhs, stringify);
|
||||||
first_conn_line = false;
|
first_conn_line = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -408,7 +440,7 @@ void RTLIL_BACKEND::dump_module(std::ostream &f, std::string indent, RTLIL::Modu
|
||||||
f << stringf("%s" "end\n", indent);
|
f << stringf("%s" "end\n", indent);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RTLIL_BACKEND::dump_design(std::ostream &f, RTLIL::Design *design, bool only_selected, bool flag_m, bool flag_n, bool resolve_src)
|
void RTLIL_BACKEND::dump_design(std::ostream &f, RTLIL::Design *design, bool only_selected, bool flag_m, bool flag_n, bool stringify)
|
||||||
{
|
{
|
||||||
int init_autoidx = autoidx;
|
int init_autoidx = autoidx;
|
||||||
|
|
||||||
|
|
@ -428,7 +460,7 @@ void RTLIL_BACKEND::dump_design(std::ostream &f, RTLIL::Design *design, bool onl
|
||||||
if (only_selected)
|
if (only_selected)
|
||||||
f << stringf("\n");
|
f << stringf("\n");
|
||||||
f << stringf("autoidx %d\n", autoidx);
|
f << stringf("autoidx %d\n", autoidx);
|
||||||
if (!resolve_src)
|
if (!stringify)
|
||||||
dump_twines(f, design);
|
dump_twines(f, design);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -436,7 +468,7 @@ void RTLIL_BACKEND::dump_design(std::ostream &f, RTLIL::Design *design, bool onl
|
||||||
if (!only_selected || design->selected_module(module->meta_->name)) {
|
if (!only_selected || design->selected_module(module->meta_->name)) {
|
||||||
if (only_selected)
|
if (only_selected)
|
||||||
f << stringf("\n");
|
f << stringf("\n");
|
||||||
dump_module(f, "", module, design, only_selected, flag_m, flag_n, resolve_src);
|
dump_module(f, "", module, design, only_selected, flag_m, flag_n, stringify);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -463,18 +495,16 @@ struct RTLILBackend : public Backend {
|
||||||
log(" -sort\n");
|
log(" -sort\n");
|
||||||
log(" sort design in-place (used to be default).\n");
|
log(" sort design in-place (used to be default).\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
log(" -resolve-src\n");
|
log(" -readable\n");
|
||||||
log(" expand twine references in src attributes inline. Without\n");
|
log(" lose information for more readable files.\n");
|
||||||
log(" this flag the design-level twine pool is emitted as a\n");
|
log(" Breaks perfect replayability.\n");
|
||||||
log(" `twines` header block and cell src attributes keep their\n");
|
|
||||||
log(" compact \"@N\" reference form.\n");
|
|
||||||
log("\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;
|
bool do_sort = false;
|
||||||
bool resolve_src = false;
|
bool stringify = false;
|
||||||
|
|
||||||
log_header(design, "Executing RTLIL backend.\n");
|
log_header(design, "Executing RTLIL backend.\n");
|
||||||
|
|
||||||
|
|
@ -489,8 +519,8 @@ struct RTLILBackend : public Backend {
|
||||||
do_sort = true;
|
do_sort = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (arg == "-resolve-src") {
|
if (arg == "-readable") {
|
||||||
resolve_src = true;
|
stringify = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
@ -503,7 +533,7 @@ struct RTLILBackend : public Backend {
|
||||||
design->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, resolve_src);
|
RTLIL_BACKEND::dump_design(*f, design, selected, true, false, stringify);
|
||||||
}
|
}
|
||||||
} RTLILBackend;
|
} RTLILBackend;
|
||||||
|
|
||||||
|
|
@ -531,17 +561,15 @@ struct DumpPass : public Pass {
|
||||||
log(" -a <filename>\n");
|
log(" -a <filename>\n");
|
||||||
log(" like -outfile but append instead of overwrite\n");
|
log(" like -outfile but append instead of overwrite\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
log(" -resolve-src\n");
|
log(" -readable\n");
|
||||||
log(" expand twine references in src attributes inline. Without\n");
|
log(" lose information for more readable files.\n");
|
||||||
log(" this flag the design-level twine pool is emitted as a\n");
|
log(" Breaks perfect replayability.\n");
|
||||||
log(" `twines` header block and cell src attributes keep their\n");
|
|
||||||
log(" compact \"@N\" reference form.\n");
|
|
||||||
log("\n");
|
log("\n");
|
||||||
}
|
}
|
||||||
void execute(std::vector<std::string> args, RTLIL::Design *design) override
|
void execute(std::vector<std::string> args, RTLIL::Design *design) override
|
||||||
{
|
{
|
||||||
std::string filename;
|
std::string filename;
|
||||||
bool flag_m = false, flag_n = false, append = false, resolve_src = false;
|
bool flag_m = false, flag_n = false, append = false, stringify = false;
|
||||||
|
|
||||||
size_t argidx;
|
size_t argidx;
|
||||||
for (argidx = 1; argidx < args.size(); argidx++)
|
for (argidx = 1; argidx < args.size(); argidx++)
|
||||||
|
|
@ -565,8 +593,8 @@ struct DumpPass : public Pass {
|
||||||
flag_n = true;
|
flag_n = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (arg == "-resolve-src") {
|
if (arg == "-readable") {
|
||||||
resolve_src = true;
|
stringify = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
@ -590,7 +618,7 @@ struct DumpPass : public Pass {
|
||||||
f = &buf;
|
f = &buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
RTLIL_BACKEND::dump_design(*f, design, true, flag_m, flag_n, resolve_src);
|
RTLIL_BACKEND::dump_design(*f, design, true, flag_m, flag_n, stringify);
|
||||||
|
|
||||||
if (!empty) {
|
if (!empty) {
|
||||||
delete f;
|
delete f;
|
||||||
|
|
|
||||||
|
|
@ -31,30 +31,22 @@
|
||||||
YOSYS_NAMESPACE_BEGIN
|
YOSYS_NAMESPACE_BEGIN
|
||||||
|
|
||||||
namespace RTLIL_BACKEND {
|
namespace RTLIL_BACKEND {
|
||||||
// If `design` is non-null AND `resolve_src` is true, the ID::src
|
void dump_attributes(std::ostream &f, std::string indent, const RTLIL::AttrObject *obj, const RTLIL::Design *design = nullptr, bool stringify = false);
|
||||||
// attribute is expanded through design->twines so the emitted
|
|
||||||
// value is the flat path:line.col string. Otherwise the stored value
|
|
||||||
// is written verbatim — including any "@N" twine references, which
|
|
||||||
// the matching `twines` header block emitted by dump_design lets the
|
|
||||||
// parser reconstruct on load.
|
|
||||||
void dump_attributes(std::ostream &f, std::string indent, const RTLIL::AttrObject *obj, const RTLIL::Design *design = nullptr, bool resolve_src = false);
|
|
||||||
|
|
||||||
// Emit the design-level twine pool as a top-level `twines` block.
|
|
||||||
// Skipped if the pool is empty.
|
|
||||||
void dump_twines(std::ostream &f, const RTLIL::Design *design);
|
void dump_twines(std::ostream &f, const RTLIL::Design *design);
|
||||||
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, bool stringify = 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, bool stringify = true);
|
||||||
void dump_wire(std::ostream &f, std::string indent, const RTLIL::Wire *wire, const RTLIL::Design *design = nullptr, bool resolve_src = false);
|
void dump_wire(std::ostream &f, std::string indent, const RTLIL::Wire *wire, const RTLIL::Design *design = nullptr, bool stringify = false);
|
||||||
void dump_memory(std::ostream &f, std::string indent, const RTLIL::Memory *memory, const RTLIL::Design *design = nullptr, bool resolve_src = false);
|
void dump_memory(std::ostream &f, std::string indent, const RTLIL::Memory *memory, const RTLIL::Design *design = nullptr, bool stringify = false);
|
||||||
void dump_cell(std::ostream &f, std::string indent, const RTLIL::Cell *cell, const RTLIL::Design *design = nullptr, bool resolve_src = false);
|
void dump_cell(std::ostream &f, std::string indent, const RTLIL::Cell *cell, const RTLIL::Design *design = nullptr, bool stringify = false);
|
||||||
void dump_proc_case_body(std::ostream &f, std::string indent, const RTLIL::CaseRule *cs, const RTLIL::Design *design = nullptr, bool resolve_src = false);
|
void dump_proc_case_body(std::ostream &f, std::string indent, const RTLIL::CaseRule *cs, const RTLIL::Design *design = nullptr, bool stringify = false);
|
||||||
void dump_proc_switch(std::ostream &f, std::string indent, const RTLIL::SwitchRule *sw, const RTLIL::Design *design = nullptr, bool resolve_src = false);
|
void dump_proc_switch(std::ostream &f, std::string indent, const RTLIL::SwitchRule *sw, const RTLIL::Design *design = nullptr, bool stringify = false);
|
||||||
void dump_proc_sync(std::ostream &f, std::string indent, const RTLIL::SyncRule *sy, const RTLIL::Design *design = nullptr, bool resolve_src = false);
|
void dump_proc_sync(std::ostream &f, std::string indent, const RTLIL::SyncRule *sy, const RTLIL::Design *design = nullptr, bool stringify = false);
|
||||||
void dump_proc(std::ostream &f, std::string indent, const RTLIL::Process *proc, const RTLIL::Design *design = nullptr, bool resolve_src = false);
|
void dump_proc(std::ostream &f, std::string indent, const RTLIL::Process *proc, const RTLIL::Design *design = nullptr, bool stringify = false);
|
||||||
void dump_conn(std::ostream &f, std::string indent, const RTLIL::SigSpec &left, const RTLIL::SigSpec &right);
|
void dump_conn(std::ostream &f, std::string indent, const RTLIL::SigSpec &left, const RTLIL::SigSpec &right, bool stringify = true);
|
||||||
void dump_module(std::ostream &f, std::string indent, RTLIL::Module *module, RTLIL::Design *design, bool only_selected, bool flag_m = true, bool flag_n = false, bool resolve_src = false);
|
void dump_module(std::ostream &f, std::string indent, RTLIL::Module *module, RTLIL::Design *design, bool only_selected, bool flag_m = true, bool flag_n = false, bool stringify = false);
|
||||||
void dump_design(std::ostream &f, RTLIL::Design *design, bool only_selected, bool flag_m = true, bool flag_n = false, bool resolve_src = false);
|
void dump_design(std::ostream &f, RTLIL::Design *design, bool only_selected, bool flag_m = true, bool flag_n = false, bool stringify = false);
|
||||||
}
|
}
|
||||||
|
|
||||||
YOSYS_NAMESPACE_END
|
YOSYS_NAMESPACE_END
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,10 @@ struct RTLILFrontendWorker {
|
||||||
|
|
||||||
RTLIL::Module *current_module;
|
RTLIL::Module *current_module;
|
||||||
dict<RTLIL::IdString, RTLIL::Const> attrbuf;
|
dict<RTLIL::IdString, RTLIL::Const> attrbuf;
|
||||||
|
// A resolved "@N" src reference, carried from parse_attribute to the
|
||||||
|
// object's absorb_attrs site so it lands on the object without being
|
||||||
|
// flattened into a fresh leaf.
|
||||||
|
TwineRef pending_src = Twine::Null;
|
||||||
std::vector<std::vector<RTLIL::SwitchRule*>*> switch_stack;
|
std::vector<std::vector<RTLIL::SwitchRule*>*> switch_stack;
|
||||||
std::vector<RTLIL::CaseRule*> case_stack;
|
std::vector<RTLIL::CaseRule*> case_stack;
|
||||||
|
|
||||||
|
|
@ -355,6 +359,16 @@ struct RTLILFrontendWorker {
|
||||||
parts.push_back(parse_sigspec());
|
parts.push_back(parse_sigspec());
|
||||||
for (auto it = parts.rbegin(); it != parts.rend(); ++it)
|
for (auto it = parts.rbegin(); it != parts.rend(); ++it)
|
||||||
sig.append(std::move(*it));
|
sig.append(std::move(*it));
|
||||||
|
} else if (std::optional<TwineRef> handle = try_parse_twine_handle()) {
|
||||||
|
TwineRef ref = *handle;
|
||||||
|
RTLIL::Wire *wire = current_module->wire(ref);
|
||||||
|
if (wire == nullptr) {
|
||||||
|
if (flag_legalize)
|
||||||
|
wire = legalize_wire(RTLIL::IdString(design->twines.str(ref)));
|
||||||
|
else
|
||||||
|
error("Wire %s not found.", design->twines.str(ref).c_str());
|
||||||
|
}
|
||||||
|
sig = RTLIL::SigSpec(wire);
|
||||||
} else {
|
} else {
|
||||||
// We could add a special path for parsing IdStrings that must already exist,
|
// We could add a special path for parsing IdStrings that must already exist,
|
||||||
// as here.
|
// as here.
|
||||||
|
|
@ -426,7 +440,7 @@ struct RTLILFrontendWorker {
|
||||||
|
|
||||||
void parse_module()
|
void parse_module()
|
||||||
{
|
{
|
||||||
TwineRef module_name = design->twines.add(parse_id());
|
TwineRef module_name = parse_twine();
|
||||||
expect_eol();
|
expect_eol();
|
||||||
|
|
||||||
bool delete_current_module = false;
|
bool delete_current_module = false;
|
||||||
|
|
@ -453,10 +467,12 @@ struct RTLILFrontendWorker {
|
||||||
// Module is about to be discarded — drop its src attribute
|
// Module is about to be discarded — drop its src attribute
|
||||||
// rather than push it into a pool we'll never reach.
|
// rather than push it into a pool we'll never reach.
|
||||||
attrbuf.erase(ID::src);
|
attrbuf.erase(ID::src);
|
||||||
|
pending_src = Twine::Null;
|
||||||
current_module->attributes = std::move(attrbuf);
|
current_module->attributes = std::move(attrbuf);
|
||||||
} else {
|
} else {
|
||||||
design->add(current_module);
|
design->add(current_module);
|
||||||
current_module->absorb_attrs(std::move(attrbuf));
|
current_module->absorb_attrs(std::move(attrbuf));
|
||||||
|
flush_src(current_module);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
|
|
@ -518,6 +534,18 @@ struct RTLILFrontendWorker {
|
||||||
// is wrong and silently interning it would hide that.
|
// is wrong and silently interning it would hide that.
|
||||||
if (id == RTLIL::ID::src && (c.flags & RTLIL::CONST_FLAG_STRING)) {
|
if (id == RTLIL::ID::src && (c.flags & RTLIL::CONST_FLAG_STRING)) {
|
||||||
std::string raw = c.decode_string();
|
std::string raw = c.decode_string();
|
||||||
|
if (!raw.empty() && raw[0] == '@') {
|
||||||
|
// Compact "@N" reference into the `twines` block: carry the
|
||||||
|
// resolved twine straight to the object (set after its
|
||||||
|
// absorb_attrs) so its structure is preserved, not flattened.
|
||||||
|
size_t file_id = 0;
|
||||||
|
auto [ptr, ec] = std::from_chars(raw.data() + 1, raw.data() + raw.size(), file_id);
|
||||||
|
if (ec != std::errc() || ptr != raw.data() + raw.size())
|
||||||
|
error("Malformed src twine reference %s at line %d", raw.c_str(), line_num);
|
||||||
|
pending_src = resolve_file_twine(file_id);
|
||||||
|
expect_eol();
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (raw.find('|') != std::string::npos) {
|
if (raw.find('|') != std::string::npos) {
|
||||||
log_warning("line %d: src attribute %s contains '|' separators. "
|
log_warning("line %d: src attribute %s contains '|' separators. "
|
||||||
"That convention is Yosys-internal; the producing tool "
|
"That convention is Yosys-internal; the producing tool "
|
||||||
|
|
@ -530,14 +558,79 @@ struct RTLILFrontendWorker {
|
||||||
expect_eol();
|
expect_eol();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Apply a pending "@N" src reference to the object just built from attrbuf.
|
||||||
|
void flush_src(RTLIL::AttrObject *obj)
|
||||||
|
{
|
||||||
|
if (pending_src != Twine::Null) {
|
||||||
|
design->set_src_attribute(obj, pending_src);
|
||||||
|
pending_src = Twine::Null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Parses a `twines` ... `end` block. Builds twine_remap so subsequent
|
// Parses a `twines` ... `end` block. Builds twine_remap so subsequent
|
||||||
// cell/wire src "@N" references (which use file-local ids) translate
|
// cell/wire src "@N" references (which use file-local ids) translate
|
||||||
// to ids in design->twines. The destination pool may already be
|
// to ids in design->twines. The destination pool may already be
|
||||||
// non-empty (multi-file load) — interned/concated nodes are dedup'd
|
// non-empty (multi-file load) — interned/concated nodes are dedup'd
|
||||||
// against the existing pool by the pool itself.
|
// against the existing pool by the pool itself.
|
||||||
|
// Static ids are universal: a file id below STATIC_TWINE_END denotes the
|
||||||
|
// same prepopulated twine in every pool, so it maps to itself and is
|
||||||
|
// never emitted in the `twines` block.
|
||||||
|
// Resolve a numeric content id from the twines block (a node's own id, or
|
||||||
|
// a suffix/concat child). Statics are universal — an id below
|
||||||
|
// STATIC_TWINE_END denotes the same prepopulated twine in every pool;
|
||||||
|
// locals are remapped per file. Publicity (for $pub@/$priv@ handles)
|
||||||
|
// travels separately and is reapplied here. Object-use statics never reach
|
||||||
|
// this path: they are written as escaped names and interned by content.
|
||||||
|
TwineRef resolve_file_twine(size_t id, bool is_public = false)
|
||||||
|
{
|
||||||
|
TwineRef base;
|
||||||
|
if (id < STATIC_TWINE_END) {
|
||||||
|
base = TwineRef(id);
|
||||||
|
} else {
|
||||||
|
auto it = twine_remap.find(id);
|
||||||
|
if (it == twine_remap.end())
|
||||||
|
error("Unknown twine reference @%zu at line %d", id, line_num);
|
||||||
|
base = it->second;
|
||||||
|
}
|
||||||
|
return twine_tag(base, is_public);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse a "$pub@N"/"$priv@N" twine handle into a resolved, retagged ref.
|
||||||
|
// Returns nullopt (consuming nothing) if the next token is not a handle.
|
||||||
|
std::optional<TwineRef> try_parse_twine_handle()
|
||||||
|
{
|
||||||
|
bool is_public;
|
||||||
|
if (line.substr(0, 5) == "$pub@")
|
||||||
|
is_public = true, line = line.substr(5);
|
||||||
|
else if (line.substr(0, 6) == "$priv@")
|
||||||
|
is_public = false, line = line.substr(6);
|
||||||
|
else
|
||||||
|
return std::nullopt;
|
||||||
|
return resolve_file_twine(parse_integer(), is_public);
|
||||||
|
}
|
||||||
|
|
||||||
|
// A twine-typed token at a definition site: a $pub@/$priv@ reference into
|
||||||
|
// the twines table, or an escaped identifier interned into the pool.
|
||||||
|
std::optional<TwineRef> try_parse_twine()
|
||||||
|
{
|
||||||
|
if (std::optional<TwineRef> handle = try_parse_twine_handle())
|
||||||
|
return handle;
|
||||||
|
std::optional<std::string> id = try_parse_id();
|
||||||
|
if (!id)
|
||||||
|
return std::nullopt;
|
||||||
|
return design->twines.add(std::move(*id));
|
||||||
|
}
|
||||||
|
|
||||||
|
TwineRef parse_twine()
|
||||||
|
{
|
||||||
|
std::optional<TwineRef> t = try_parse_twine();
|
||||||
|
if (!t)
|
||||||
|
error("Expected twine reference or ID, got `%s'.", error_token());
|
||||||
|
return *t;
|
||||||
|
}
|
||||||
|
|
||||||
void parse_twines()
|
void parse_twines()
|
||||||
{
|
{
|
||||||
dict<size_t, Twine> file_twines;
|
|
||||||
expect_eol();
|
expect_eol();
|
||||||
while (true) {
|
while (true) {
|
||||||
if (try_parse_keyword("end"))
|
if (try_parse_keyword("end"))
|
||||||
|
|
@ -546,7 +639,7 @@ struct RTLILFrontendWorker {
|
||||||
size_t file_id = parse_integer();
|
size_t file_id = parse_integer();
|
||||||
std::string text = parse_string();
|
std::string text = parse_string();
|
||||||
expect_eol();
|
expect_eol();
|
||||||
file_twines[file_id] = Twine{text};
|
twine_remap[file_id] = design->twines.add(Twine{text});
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (try_parse_keyword("suffix")) {
|
if (try_parse_keyword("suffix")) {
|
||||||
|
|
@ -554,30 +647,21 @@ struct RTLILFrontendWorker {
|
||||||
size_t file_parent = parse_integer();
|
size_t file_parent = parse_integer();
|
||||||
std::string tail = parse_string();
|
std::string tail = parse_string();
|
||||||
expect_eol();
|
expect_eol();
|
||||||
if (twine_remap.count(file_parent) == 0)
|
twine_remap[file_id] = design->twines.add(Twine{Twine::Suffix{resolve_file_twine(file_parent), tail}});
|
||||||
error("Unknown parent twine @%zu for suffix at line %d", file_parent, line_num);
|
|
||||||
file_twines[file_id] = Twine{Twine::Suffix{twine_remap[file_parent], tail}};
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (try_parse_keyword("concat")) {
|
if (try_parse_keyword("concat")) {
|
||||||
size_t file_id = parse_integer();
|
size_t file_id = parse_integer();
|
||||||
std::vector<TwineRef> children;
|
std::vector<TwineRef> children;
|
||||||
while (!try_parse_eol()) {
|
while (!try_parse_eol())
|
||||||
size_t child_id = parse_integer();
|
children.push_back(resolve_file_twine(parse_integer()));
|
||||||
if (twine_remap.count(child_id) == 0)
|
twine_remap[file_id] = design->twines.add(Twine{children});
|
||||||
error("Unknown child twine @%zu for concat at line %d", child_id, line_num);
|
|
||||||
children.push_back(twine_remap[child_id]);
|
|
||||||
}
|
|
||||||
file_twines[file_id] = Twine{children};
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
error("Expected `leaf`, `suffix` or `concat` inside twines block, got `%s'.",
|
error("Expected `leaf`, `suffix` or `concat` inside twines block, got `%s'.",
|
||||||
error_token());
|
error_token());
|
||||||
}
|
}
|
||||||
expect_eol();
|
expect_eol();
|
||||||
for (auto &p : file_twines) {
|
|
||||||
twine_remap[p.first] = design->twines.add(std::move(p.second));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Release the per-file parser refs gathered during parse_twines. Call
|
// Release the per-file parser refs gathered during parse_twines. Call
|
||||||
|
|
@ -613,18 +697,16 @@ struct RTLILFrontendWorker {
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
std::optional<std::string> id = try_parse_id();
|
std::optional<TwineRef> name = try_parse_twine();
|
||||||
if (id) {
|
if (name) {
|
||||||
TwineRef wire_name = design->twines.lookup(*id);
|
TwineRef wire_name = *name;
|
||||||
if (wire_name == Twine::Null)
|
|
||||||
wire_name = design->twines.add(std::move(*id));
|
|
||||||
if (current_module->wire(wire_name) != nullptr) {
|
if (current_module->wire(wire_name) != nullptr) {
|
||||||
if (flag_legalize) {
|
if (flag_legalize) {
|
||||||
log("Legalizing redefinition of wire %s.\n", *id);
|
log("Legalizing redefinition of wire %s.\n", design->twines.str(wire_name).c_str());
|
||||||
pool<RTLIL::Wire*> wires = {current_module->wire(wire_name)};
|
pool<RTLIL::Wire*> wires = {current_module->wire(wire_name)};
|
||||||
current_module->remove(wires);
|
current_module->remove(wires);
|
||||||
} else
|
} else
|
||||||
error("RTLIL error: redefinition of wire %s.", *id);
|
error("RTLIL error: redefinition of wire %s.", design->twines.str(wire_name).c_str());
|
||||||
}
|
}
|
||||||
wire = current_module->addWire(wire_name);
|
wire = current_module->addWire(wire_name);
|
||||||
break;
|
break;
|
||||||
|
|
@ -654,6 +736,7 @@ struct RTLILFrontendWorker {
|
||||||
}
|
}
|
||||||
|
|
||||||
wire->absorb_attrs(std::move(attrbuf));
|
wire->absorb_attrs(std::move(attrbuf));
|
||||||
|
flush_src(wire);
|
||||||
wire->width = width;
|
wire->width = width;
|
||||||
wire->upto = upto;
|
wire->upto = upto;
|
||||||
wire->start_offset = start_offset;
|
wire->start_offset = start_offset;
|
||||||
|
|
@ -669,6 +752,7 @@ struct RTLILFrontendWorker {
|
||||||
RTLIL::Memory *memory = new RTLIL::Memory;
|
RTLIL::Memory *memory = new RTLIL::Memory;
|
||||||
memory->module = current_module;
|
memory->module = current_module;
|
||||||
memory->absorb_attrs(std::move(attrbuf));
|
memory->absorb_attrs(std::move(attrbuf));
|
||||||
|
flush_src(memory);
|
||||||
|
|
||||||
int width = 1;
|
int width = 1;
|
||||||
int start_offset = 0;
|
int start_offset = 0;
|
||||||
|
|
@ -676,17 +760,15 @@ struct RTLILFrontendWorker {
|
||||||
TwineRef mem_name = Twine::Null;
|
TwineRef mem_name = Twine::Null;
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
std::optional<RTLIL::IdString> id = try_parse_id();
|
std::optional<TwineRef> name = try_parse_twine();
|
||||||
if (id.has_value()) {
|
if (name.has_value()) {
|
||||||
mem_name = design->twines.lookup(id->str());
|
mem_name = *name;
|
||||||
if (mem_name == Twine::Null)
|
|
||||||
mem_name = design->twines.add(Twine{id->str()});
|
|
||||||
if (current_module->memories.count(mem_name) != 0) {
|
if (current_module->memories.count(mem_name) != 0) {
|
||||||
if (flag_legalize) {
|
if (flag_legalize) {
|
||||||
log("Legalizing redefinition of memory %s.\n", *id);
|
log("Legalizing redefinition of memory %s.\n", design->twines.str(mem_name).c_str());
|
||||||
current_module->remove(current_module->memories.at(mem_name));
|
current_module->remove(current_module->memories.at(mem_name));
|
||||||
} else
|
} else
|
||||||
error("RTLIL error: redefinition of memory %s.", *id);
|
error("RTLIL error: redefinition of memory %s.", design->twines.str(mem_name).c_str());
|
||||||
}
|
}
|
||||||
memory->meta_->name = mem_name;
|
memory->meta_->name = mem_name;
|
||||||
break;
|
break;
|
||||||
|
|
@ -722,37 +804,27 @@ struct RTLILFrontendWorker {
|
||||||
|
|
||||||
void parse_cell()
|
void parse_cell()
|
||||||
{
|
{
|
||||||
RTLIL::IdString cell_type = parse_id();
|
TwineRef cell_type_ref = parse_twine();
|
||||||
std::string cell_name_str = parse_id();
|
TwineRef cell_name_ref = parse_twine();
|
||||||
expect_eol();
|
expect_eol();
|
||||||
|
|
||||||
TwineRef cell_name_ref = design->twines.lookup(cell_name_str);
|
|
||||||
if (cell_name_ref == Twine::Null)
|
|
||||||
cell_name_ref = design->twines.add(Twine{cell_name_str});
|
|
||||||
|
|
||||||
if (current_module->cell(cell_name_ref) != nullptr) {
|
if (current_module->cell(cell_name_ref) != nullptr) {
|
||||||
if (flag_legalize) {
|
if (flag_legalize) {
|
||||||
|
std::string base = design->twines.str(cell_name_ref);
|
||||||
std::string new_name_str;
|
std::string new_name_str;
|
||||||
int suffix = 1;
|
int suffix = 1;
|
||||||
do {
|
do {
|
||||||
new_name_str = cell_name_str + "_" + std::to_string(suffix);
|
new_name_str = base + "_" + std::to_string(suffix);
|
||||||
TwineRef test_ref = design->twines.lookup(new_name_str);
|
cell_name_ref = design->twines.add(std::string(new_name_str));
|
||||||
if (test_ref == Twine::Null)
|
|
||||||
test_ref = design->twines.add(Twine{new_name_str});
|
|
||||||
++suffix;
|
++suffix;
|
||||||
if (current_module->cell(test_ref) == nullptr)
|
} while (current_module->cell(cell_name_ref) != nullptr);
|
||||||
break;
|
log("Legalizing redefinition of cell %s by renaming to %s.\n", base.c_str(), new_name_str.c_str());
|
||||||
} while (true);
|
|
||||||
log("Legalizing redefinition of cell %s by renaming to %s.\n", cell_name_str, new_name_str);
|
|
||||||
cell_name_str = new_name_str;
|
|
||||||
cell_name_ref = design->twines.lookup(cell_name_str);
|
|
||||||
if (cell_name_ref == Twine::Null)
|
|
||||||
cell_name_ref = design->twines.add(Twine{cell_name_str});
|
|
||||||
} else
|
} else
|
||||||
error("RTLIL error: redefinition of cell %s.", cell_name_str);
|
error("RTLIL error: redefinition of cell %s.", design->twines.str(cell_name_ref).c_str());
|
||||||
}
|
}
|
||||||
RTLIL::Cell *cell = current_module->addCell(cell_name_ref, design->twines.add(Twine{cell_type.str()}));
|
RTLIL::Cell *cell = current_module->addCell(cell_name_ref, cell_type_ref);
|
||||||
cell->absorb_attrs(std::move(attrbuf));
|
cell->absorb_attrs(std::move(attrbuf));
|
||||||
|
flush_src(cell);
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
|
|
@ -778,13 +850,12 @@ struct RTLILFrontendWorker {
|
||||||
cell->parameters.insert({std::move(param_name), std::move(val)});
|
cell->parameters.insert({std::move(param_name), std::move(val)});
|
||||||
expect_eol();
|
expect_eol();
|
||||||
} else if (try_parse_keyword("connect")) {
|
} else if (try_parse_keyword("connect")) {
|
||||||
std::string port_name_str = parse_id();
|
TwineRef port_name = parse_twine();
|
||||||
TwineRef port_name = design->twines.add(Twine{port_name_str});
|
|
||||||
if (cell->hasPort(port_name)) {
|
if (cell->hasPort(port_name)) {
|
||||||
if (flag_legalize)
|
if (flag_legalize)
|
||||||
log("Legalizing redefinition of cell port %s.", port_name_str);
|
log("Legalizing redefinition of cell port %s.", design->twines.str(port_name).c_str());
|
||||||
else
|
else
|
||||||
error("RTLIL error: redefinition of cell port %s.", port_name_str);
|
error("RTLIL error: redefinition of cell port %s.", design->twines.str(port_name).c_str());
|
||||||
}
|
}
|
||||||
cell->setPort(port_name, parse_sigspec());
|
cell->setPort(port_name, parse_sigspec());
|
||||||
if (flag_legalize)
|
if (flag_legalize)
|
||||||
|
|
@ -845,6 +916,7 @@ struct RTLILFrontendWorker {
|
||||||
rule->module = current_module;
|
rule->module = current_module;
|
||||||
rule->signal = parse_sigspec();
|
rule->signal = parse_sigspec();
|
||||||
rule->absorb_attrs(std::move(attrbuf));
|
rule->absorb_attrs(std::move(attrbuf));
|
||||||
|
flush_src(rule);
|
||||||
switch_stack.back()->push_back(rule);
|
switch_stack.back()->push_back(rule);
|
||||||
expect_eol();
|
expect_eol();
|
||||||
|
|
||||||
|
|
@ -863,6 +935,7 @@ struct RTLILFrontendWorker {
|
||||||
RTLIL::CaseRule *case_rule = new RTLIL::CaseRule;
|
RTLIL::CaseRule *case_rule = new RTLIL::CaseRule;
|
||||||
case_rule->module = current_module;
|
case_rule->module = current_module;
|
||||||
case_rule->absorb_attrs(std::move(attrbuf));
|
case_rule->absorb_attrs(std::move(attrbuf));
|
||||||
|
flush_src(case_rule);
|
||||||
rule->cases.push_back(case_rule);
|
rule->cases.push_back(case_rule);
|
||||||
switch_stack.push_back(&case_rule->switches);
|
switch_stack.push_back(&case_rule->switches);
|
||||||
case_stack.push_back(case_rule);
|
case_stack.push_back(case_rule);
|
||||||
|
|
@ -885,22 +958,19 @@ struct RTLILFrontendWorker {
|
||||||
|
|
||||||
void parse_process()
|
void parse_process()
|
||||||
{
|
{
|
||||||
std::string proc_name_str = parse_id();
|
TwineRef proc_name = parse_twine();
|
||||||
expect_eol();
|
expect_eol();
|
||||||
|
|
||||||
TwineRef proc_name = design->twines.lookup(proc_name_str);
|
|
||||||
if (proc_name == Twine::Null)
|
|
||||||
proc_name = design->twines.add(Twine{proc_name_str});
|
|
||||||
|
|
||||||
if (current_module->processes.count(proc_name) != 0) {
|
if (current_module->processes.count(proc_name) != 0) {
|
||||||
if (flag_legalize) {
|
if (flag_legalize) {
|
||||||
log("Legalizing redefinition of process %s.\n", proc_name_str);
|
log("Legalizing redefinition of process %s.\n", design->twines.str(proc_name).c_str());
|
||||||
current_module->remove(current_module->processes.at(proc_name));
|
current_module->remove(current_module->processes.at(proc_name));
|
||||||
} else
|
} else
|
||||||
error("RTLIL error: redefinition of process %s.", proc_name_str);
|
error("RTLIL error: redefinition of process %s.", design->twines.str(proc_name).c_str());
|
||||||
}
|
}
|
||||||
RTLIL::Process *proc = current_module->addProcess(Twine{proc_name_str});
|
RTLIL::Process *proc = current_module->addProcess(proc_name);
|
||||||
proc->absorb_attrs(std::move(attrbuf));
|
proc->absorb_attrs(std::move(attrbuf));
|
||||||
|
flush_src(proc);
|
||||||
|
|
||||||
switch_stack.clear();
|
switch_stack.clear();
|
||||||
switch_stack.push_back(&proc->root_case.switches);
|
switch_stack.push_back(&proc->root_case.switches);
|
||||||
|
|
@ -951,6 +1021,7 @@ struct RTLILFrontendWorker {
|
||||||
RTLIL::MemWriteAction act;
|
RTLIL::MemWriteAction act;
|
||||||
act.module = current_module;
|
act.module = current_module;
|
||||||
design->absorb_attrs(&act, std::move(attrbuf));
|
design->absorb_attrs(&act, std::move(attrbuf));
|
||||||
|
flush_src(&act);
|
||||||
act.memid = parse_id();
|
act.memid = parse_id();
|
||||||
act.address = parse_sigspec();
|
act.address = parse_sigspec();
|
||||||
act.data = parse_sigspec();
|
act.data = parse_sigspec();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue