From cd7bf115b668da8e59b07b939ab17771da983983 Mon Sep 17 00:00:00 2001 From: whitequark Date: Thu, 11 Jun 2020 22:21:30 +0000 Subject: cxxrtl: simplify unbuffering of input wires. This also fixes an edge case with (*keep*) input ports. --- backends/cxxrtl/cxxrtl_backend.cc | 37 +++++++++++++++++-------------------- 1 file changed, 17 insertions(+), 20 deletions(-) (limited to 'backends/cxxrtl/cxxrtl_backend.cc') diff --git a/backends/cxxrtl/cxxrtl_backend.cc b/backends/cxxrtl/cxxrtl_backend.cc index 052053c52..0a810b8d1 100644 --- a/backends/cxxrtl/cxxrtl_backend.cc +++ b/backends/cxxrtl/cxxrtl_backend.cc @@ -171,11 +171,6 @@ struct Scheduler { } }; -bool is_input_wire(const RTLIL::Wire *wire) -{ - return wire->port_input && !wire->port_output; -} - bool is_unary_cell(RTLIL::IdString type) { return type.in( @@ -804,7 +799,7 @@ struct CxxrtlWorker { default: log_assert(false); } - } else if (unbuffered_wires[chunk.wire] || is_input_wire(chunk.wire)) { + } else if (unbuffered_wires[chunk.wire]) { f << mangle(chunk.wire); } else { f << mangle(chunk.wire) << (is_lhs ? ".next" : ".curr"); @@ -1440,12 +1435,11 @@ struct CxxrtlWorker { if (elided_wires.count(wire)) return; - if (unbuffered_wires[wire]) { - if (localized_wires[wire] == is_local_context) { - dump_attrs(wire); - f << indent << "value<" << wire->width << "> " << mangle(wire) << ";\n"; - } - } else if (!is_local_context) { + if (localized_wires[wire] && is_local_context) { + dump_attrs(wire); + f << indent << "value<" << wire->width << "> " << mangle(wire) << ";\n"; + } + if (!localized_wires[wire] && !is_local_context) { std::string width; if (wire->module->has_attribute(ID(cxxrtl_blackbox)) && wire->has_attribute(ID(cxxrtl_width))) { width = wire->get_string_attribute(ID(cxxrtl_width)); @@ -1454,14 +1448,14 @@ struct CxxrtlWorker { } dump_attrs(wire); - f << indent << (is_input_wire(wire) ? "value" : "wire") << "<" << width << "> " << mangle(wire); + f << indent << (unbuffered_wires[wire] ? "value" : "wire") << "<" << width << "> " << mangle(wire); if (wire->has_attribute(ID::init)) { f << " "; dump_const_init(wire->attributes.at(ID::init)); } f << ";\n"; if (edge_wires[wire]) { - if (is_input_wire(wire)) { + if (unbuffered_wires[wire]) { f << indent << "value<" << width << "> prev_" << mangle(wire); if (wire->has_attribute(ID::init)) { f << " "; @@ -1472,7 +1466,7 @@ struct CxxrtlWorker { for (auto edge_type : edge_types) { if (edge_type.first.wire == wire) { std::string prev, next; - if (is_input_wire(wire)) { + if (unbuffered_wires[wire]) { prev = "prev_" + mangle(edge_type.first.wire); next = mangle(edge_type.first.wire); } else { @@ -1595,9 +1589,9 @@ struct CxxrtlWorker { inc_indent(); f << indent << "bool changed = false;\n"; for (auto wire : module->wires()) { - if (elided_wires.count(wire) || unbuffered_wires.count(wire)) + if (elided_wires.count(wire)) continue; - if (is_input_wire(wire)) { + if (unbuffered_wires[wire]) { if (edge_wires[wire]) f << indent << "prev_" << mangle(wire) << " = " << mangle(wire) << ";\n"; continue; @@ -1970,6 +1964,8 @@ struct CxxrtlWorker { if (module->get_bool_attribute(ID(cxxrtl_blackbox))) { for (auto port : module->ports) { RTLIL::Wire *wire = module->wire(port); + if (wire->port_input && !wire->port_output) + unbuffered_wires.insert(wire); if (wire->has_attribute(ID(cxxrtl_edge))) { RTLIL::Const edge_attr = wire->attributes[ID(cxxrtl_edge)]; if (!(edge_attr.flags & RTLIL::CONST_FLAG_STRING) || (int)edge_attr.decode_string().size() != GetSize(wire)) @@ -2158,13 +2154,14 @@ struct CxxrtlWorker { for (auto wire : module->wires()) { if (feedback_wires[wire]) continue; - if (wire->port_id != 0) continue; - if (wire->get_bool_attribute(ID::keep)) continue; + if (wire->port_output) continue; if (wire->name.begins_with("$") && !unbuffer_internal) continue; if (wire->name.begins_with("\\") && !unbuffer_public) continue; - if (edge_wires[wire]) continue; if (flow.wire_sync_defs.count(wire) > 0) continue; unbuffered_wires.insert(wire); + if (edge_wires[wire]) continue; + if (wire->get_bool_attribute(ID::keep)) continue; + if (wire->port_input || wire->port_output) continue; if (wire->name.begins_with("$") && !localize_internal) continue; if (wire->name.begins_with("\\") && !localize_public) continue; localized_wires.insert(wire); -- cgit v1.2.3 From 29bd81d66239b22ffdbe1f72416624823d712d34 Mon Sep 17 00:00:00 2001 From: whitequark Date: Fri, 12 Jun 2020 00:05:05 +0000 Subject: cxxrtl: unbuffer output wires of toplevel module. Without unbuffering output wires of, at least, toplevel modules, it is not possible to have most designs that rely on IO via toplevel ports (as opposed to using exclusively blackboxes) converge within one delta cycle. That seriously impairs the performance of CXXRTL. This commit avoids unbuffering outputs of all modules solely so that in future, CXXRTL could gain fully separate compilation, and not for any present technical reason. --- backends/cxxrtl/cxxrtl_backend.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'backends/cxxrtl/cxxrtl_backend.cc') diff --git a/backends/cxxrtl/cxxrtl_backend.cc b/backends/cxxrtl/cxxrtl_backend.cc index 0a810b8d1..c6b8bbc47 100644 --- a/backends/cxxrtl/cxxrtl_backend.cc +++ b/backends/cxxrtl/cxxrtl_backend.cc @@ -2154,7 +2154,7 @@ struct CxxrtlWorker { for (auto wire : module->wires()) { if (feedback_wires[wire]) continue; - if (wire->port_output) continue; + if (wire->port_output && !module->get_bool_attribute(ID::top)) continue; if (wire->name.begins_with("$") && !unbuffer_internal) continue; if (wire->name.begins_with("\\") && !unbuffer_public) continue; if (flow.wire_sync_defs.count(wire) > 0) continue; -- cgit v1.2.3 From d5ecd4a570a34f5315824a5bfbd740f7fb1866fa Mon Sep 17 00:00:00 2001 From: whitequark Date: Fri, 12 Jun 2020 00:35:18 +0000 Subject: cxxrtl: annotate port direction as comments. --- backends/cxxrtl/cxxrtl_backend.cc | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'backends/cxxrtl/cxxrtl_backend.cc') diff --git a/backends/cxxrtl/cxxrtl_backend.cc b/backends/cxxrtl/cxxrtl_backend.cc index c6b8bbc47..a4ef38128 100644 --- a/backends/cxxrtl/cxxrtl_backend.cc +++ b/backends/cxxrtl/cxxrtl_backend.cc @@ -1448,7 +1448,14 @@ struct CxxrtlWorker { } dump_attrs(wire); - f << indent << (unbuffered_wires[wire] ? "value" : "wire") << "<" << width << "> " << mangle(wire); + f << indent; + if (wire->port_input && wire->port_output) + f << "/*inout*/ "; + else if (wire->port_input) + f << "/*input*/ "; + else if (wire->port_output) + f << "/*output*/ "; + f << (unbuffered_wires[wire] ? "value" : "wire") << "<" << width << "> " << mangle(wire); if (wire->has_attribute(ID::init)) { f << " "; dump_const_init(wire->attributes.at(ID::init)); -- cgit v1.2.3