}
};
+bool is_input_wire(const RTLIL::Wire *wire)
+{
+ return wire->port_input && !wire->port_output;
+}
+
bool is_cxxrtl_blackbox_cell(const RTLIL::Cell *cell)
{
RTLIL::Module *cell_module = cell->module->design->module(cell->type);
default:
log_assert(false);
}
- } else if (localized_wires[chunk.wire]) {
+ } else if (localized_wires[chunk.wire] || is_input_wire(chunk.wire)) {
f << mangle(chunk.wire);
} else {
f << mangle(chunk.wire) << (is_lhs ? ".next" : ".curr");
log_assert(cell->known());
const char *access = is_cxxrtl_blackbox_cell(cell) ? "->" : ".";
for (auto conn : cell->connections())
- if (cell->input(conn.first)) {
+ if (cell->input(conn.first) && !cell->output(conn.first)) {
+ f << indent << mangle(cell) << access << mangle_wire_name(conn.first) << " = ";
+ dump_sigspec_rhs(conn.second);
+ f << ";\n";
+ } else if (cell->input(conn.first)) {
f << indent << mangle(cell) << access << mangle_wire_name(conn.first) << ".next = ";
dump_sigspec_rhs(conn.second);
f << ";\n";
}
}
- void dump_wire(const RTLIL::Wire *wire, bool is_local)
+ void dump_wire(const RTLIL::Wire *wire, bool is_local_context)
{
if (elided_wires.count(wire))
return;
+ if (localized_wires.count(wire) != is_local_context)
+ return;
- if (is_local) {
- if (!localized_wires.count(wire))
- return;
-
+ if (is_local_context) {
dump_attrs(wire);
f << indent << "value<" << wire->width << "> " << mangle(wire) << ";\n";
} else {
- if (localized_wires.count(wire))
- return;
-
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));
}
dump_attrs(wire);
- f << indent << "wire<" << width << "> " << mangle(wire);
+ f << indent << (is_input_wire(wire) ? "value" : "wire") << "<" << width << "> " << mangle(wire);
if (wire->has_attribute(ID::init)) {
f << " ";
dump_const_init(wire->attributes.at(ID::init));
}
f << ";\n";
if (sync_wires[wire]) {
+ if (is_input_wire(wire)) {
+ f << indent << "value<" << width << "> prev_" << mangle(wire);
+ if (wire->has_attribute(ID::init)) {
+ f << " ";
+ dump_const_init(wire->attributes.at(ID::init));
+ }
+ f << ";\n";
+ }
for (auto sync_type : sync_types) {
if (sync_type.first.wire == wire) {
+ std::string prev, next;
+ if (is_input_wire(wire)) {
+ prev = "prev_" + mangle(sync_type.first.wire);
+ next = mangle(sync_type.first.wire);
+ } else {
+ prev = mangle(sync_type.first.wire) + ".curr";
+ next = mangle(sync_type.first.wire) + ".next";
+ }
+ prev += ".slice<" + std::to_string(sync_type.first.offset) + ">().val()";
+ next += ".slice<" + std::to_string(sync_type.first.offset) + ">().val()";
if (sync_type.second != RTLIL::STn) {
f << indent << "bool posedge_" << mangle(sync_type.first) << "() const {\n";
inc_indent();
- f << indent << "return ";
- f << "!" << mangle(sync_type.first.wire) << ".curr.slice<" << sync_type.first.offset << ">().val() && ";
- f << mangle(sync_type.first.wire) << ".next.slice<" << sync_type.first.offset << ">().val();\n";
+ f << indent << "return !" << prev << " && " << next << ";\n";
dec_indent();
f << indent << "}\n";
- } else {
+ }
+ if (sync_type.second != RTLIL::STp) {
f << indent << "bool negedge_" << mangle(sync_type.first) << "() const {\n";
inc_indent();
- f << indent << "return ";
- f << mangle(sync_type.first.wire) << ".curr.slice<" << sync_type.first.offset << ">().val() && ";
- f << "!" << mangle(sync_type.first.wire) << ".next.slice<" << sync_type.first.offset << ">().val();\n";
+ f << indent << "return " << prev << " && !" << next << ";\n";
dec_indent();
f << indent << "}\n";
}
inc_indent();
if (!module->get_bool_attribute(ID(cxxrtl.blackbox))) {
for (auto wire : module->wires())
- dump_wire(wire, /*is_local=*/true);
+ dump_wire(wire, /*is_local_context=*/true);
for (auto node : schedule[module]) {
switch (node.type) {
case FlowGraph::Node::Type::CONNECT:
for (auto wire : module->wires()) {
if (elided_wires.count(wire) || localized_wires.count(wire))
continue;
+ if (is_input_wire(wire)) {
+ if (sync_wires[wire])
+ f << indent << "prev_" << mangle(wire) << " = " << mangle(wire) << ";\n";
+ continue;
+ }
if (!module->get_bool_attribute(ID(cxxrtl.blackbox)) || wire->port_id != 0)
f << indent << "changed |= " << mangle(wire) << ".commit();\n";
}
inc_indent();
for (auto wire : module->wires()) {
if (wire->port_id != 0)
- dump_wire(wire, /*is_local=*/false);
+ dump_wire(wire, /*is_local_context=*/false);
}
f << "\n";
f << indent << "void eval() override {\n";
f << indent << "struct " << mangle(module) << " : public module {\n";
inc_indent();
for (auto wire : module->wires())
- dump_wire(wire, /*is_local=*/false);
+ dump_wire(wire, /*is_local_context=*/false);
f << "\n";
bool has_memories = false;
for (auto memory : module->memories) {
log(" top.step();\n");
log(" while (1) {\n");
log(" /* user logic */\n");
- log(" top.p_clk.next = value<1> {0u};\n");
+ log(" top.p_clk = value<1> {0u};\n");
log(" top.step();\n");
- log(" top.p_clk.next = value<1> {1u};\n");
+ log(" top.p_clk = value<1> {1u};\n");
log(" top.step();\n");
log(" }\n");
log(" }\n");
log(" module debug(...);\n");
log(" (* cxxrtl.edge = \"p\" *) input clk;\n");
log(" input en;\n");
- log(" input [7:0] data;\n");
+ log(" input [7:0] i_data;\n");
+ log(" output [7:0] o_data;\n");
log(" endmodule\n");
log("\n");
log("For this HDL interface, this backend will generate the following C++ interface:\n");
log("\n");
log(" struct bb_p_debug : public module {\n");
- log(" wire<1> p_clk;\n");
+ log(" value<1> p_clk;\n");
log(" bool posedge_p_clk() const { /* ... */ }\n");
- log(" wire<1> p_en;\n");
- log(" wire<8> p_data;\n");
+ log(" value<1> p_en;\n");
+ log(" value<8> p_i_data;\n");
+ log(" wire<8> p_o_data;\n");
log("\n");
log(" void eval() override;\n");
log(" bool commit() override;\n");
log("\n");
log(" struct stderr_debug : public bb_p_debug {\n");
log(" void eval() override {\n");
- log(" if (posedge_p_clk() && p_en.curr)\n");
- log(" fprintf(stderr, \"debug: %%02x\\n\", p_data.curr.data[0]);\n");
+ log(" if (posedge_p_clk() && p_en)\n");
+ log(" fprintf(stderr, \"debug: %%02x\\n\", p_i_data.data[0]);\n");
+ log(" p_o_data.next = p_i_data;\n");
log(" bb_p_debug::eval();\n");
log(" }\n");
log(" };\n");
log(" parameter WIDTH = 8;\n");
log(" (* cxxrtl.edge = \"p\" *) input clk;\n");
log(" input en;\n");
- log(" (* cxxrtl.width = \"WIDTH\" *) input [WIDTH - 1:0] data;\n");
+ log(" (* cxxrtl.width = \"WIDTH\" *) input [WIDTH - 1:0] i_data;\n");
+ log(" (* cxxrtl.width = \"WIDTH\" *) output [WIDTH - 1:0] o_data;\n");
log(" endmodule\n");
log("\n");
log("For this parametric HDL interface, this backend will generate the following C++\n");
log(" template<size_t WIDTH>\n");
log(" struct bb_p_debug : public module {\n");
log(" // ...\n");
- log(" wire<WIDTH> p_data;\n");
+ log(" value<WIDTH> p_i_data;\n");
+ log(" wire<WIDTH> p_o_data;\n");
log(" // ...\n");
log(" static std::unique_ptr<bb_p_debug<WIDTH>>\n");
log(" create(std::string name, metadata_map parameters, metadata_map attributes);\n");