cxxrtl: WIP: adjust comb display cells to only fire on change

Naming and use of statics to be possibly revised.
This commit is contained in:
Charlotte 2023-06-28 11:51:30 +10:00 committed by Marcelina Kościelnicka
parent 7f7c61c9f0
commit 843ad9331b
8 changed files with 95 additions and 16 deletions

View File

@ -850,7 +850,7 @@ std::ostream &operator<<(std::ostream &os, const value_formatted<Bits> &vf)
while (!val.is_zero()) {
value<Bits> quotient;
val.divideWithRemainder(value<Bits>{10u}, quotient);
buf += '0' + val.template slice<3, 0>().val().template get<uint8_t>();
buf += '0' + val.template trunc<(Bits > 4 ? 4 : Bits)>().val().template get<uint8_t>();
val = quotient;
}
if (negative || vf.plus)

View File

@ -1217,8 +1217,18 @@ struct CxxrtlWorker {
// $print cell
} else if (cell->type == ID($print)) {
log_assert(!for_debug);
auto trg_enable = cell->getParam(ID::TRG_ENABLE).as_bool();
static int cell_counter = 0;
if (!trg_enable) {
++cell_counter;
f << indent << "static bool last_print_" << cell_counter << "_known = false;\n";
f << indent << "static value<1> last_print_" << cell_counter << "_en;\n";
f << indent << "static value<" << cell->getPort(ID::ARGS).size() << "> last_print_" << cell_counter << "_args;\n";
}
f << indent << "if (";
if (cell->getParam(ID::TRG_ENABLE).as_bool()) {
if (trg_enable) {
f << '(';
for (size_t i = 0; i < (size_t)cell->getParam(ID::TRG_WIDTH).as_int(); i++) {
RTLIL::SigBit trg_bit = cell->getPort(ID::TRG)[i];
@ -1235,6 +1245,17 @@ struct CxxrtlWorker {
f << mangle(trg_bit);
}
f << ") && ";
} else {
f << '(';
f << "!last_print_" << cell_counter << "_known || ";
f << '(';
f << "last_print_" << cell_counter << "_en != ";
dump_sigspec_rhs(cell->getPort(ID::EN));
f << " || last_print_" << cell_counter << "_args != ";
dump_sigspec_rhs(cell->getPort(ID::ARGS));
f << ')';
f << ") && ";
}
dump_sigspec_rhs(cell->getPort(ID::EN));
f << " == value<1>{1u}) {\n";
@ -1242,6 +1263,16 @@ struct CxxrtlWorker {
dump_print(cell);
dec_indent();
f << indent << "}\n";
if (!trg_enable) {
f << indent << "last_print_" << cell_counter << "_known = true;\n";
f << indent << "last_print_" << cell_counter << "_en = ";
dump_sigspec_rhs(cell->getPort(ID::EN));
f << ";\n";
f << indent << "last_print_" << cell_counter << "_args = ";
dump_sigspec_rhs(cell->getPort(ID::ARGS));
f << ";\n";
}
// Flip-flops
} else if (is_ff_cell(cell->type)) {
log_assert(!for_debug);

View File

@ -641,8 +641,8 @@ has the following parameters:
The width (in bits) of the signal on the ``\ARGS`` port.
``\TRG_ENABLE``
True if only triggered on specific signals defined in ``\TRG``; false if
executed on every step.
True if triggered on specific signals defined in ``\TRG``; false if
triggered whenever ``\ARGS`` or ``\EN`` change and ``\EN`` is 1.
If ``\TRG_ENABLE`` is true, the following parameters are also set:

24
tests/fmt/always_comb.v Normal file
View File

@ -0,0 +1,24 @@
module top(input clk);
reg a = 0;
reg b = 0;
wire y;
sub s (.a(a), .b(b), .y(y));
always @(posedge clk) begin
a <= (!a && !b) || (a && !b);
b <= (a && !b) || (a && b);
end
endmodule
module sub(input a, input b, output wire y);
assign y = a & b;
// Not fit for our purposes: always @* if (a) $display(a, b, y);
//
// We compare output against iverilog, but async iverilog $display fires
// even before values have propagated -- i.e. combinations of a/b/y will be
// shown where a & b are both 1, but y has not yet taken the value 1. We
// don't, so we specify it in the conditional.
always @* if (y & (y == (a & b))) $display(a, b, y);
endmodule

View File

@ -0,0 +1,14 @@
#include <iostream>
#include "yosys-always_comb.cc"
int main()
{
cxxrtl_design::p_top uut;
for (int i = 0; i < 20; ++i) {
uut.p_clk.set(!uut.p_clk);
uut.step();
}
return 0;
}

View File

@ -0,0 +1,8 @@
module tb;
reg clk = 0;
top uut (.clk(clk));
always #1 clk <= ~clk;
initial #20 $finish;
endmodule

View File

@ -8,8 +8,6 @@ module always_full(input clk, output reg fin);
if (counter == 0) fin <= 0;
if (counter == 1) $display("<<<BEGIN>>>");
if (counter == 2) $display("==> small unsigned %%d");
if (counter == 3) $display(":%d:", 16'haa);
if (counter == 4) $display(":%-d:", 16'haa);
@ -239,10 +237,7 @@ module always_full(input clk, output reg fin);
if (counter == 207) $display("==> write/format");
if (counter == 208) $display("%d", 1, "%d", 1);
if (counter == 209) begin
$display("<<<END>>>");
fin <= 1;
end
if (counter == 209) fin <= 1;
end

View File

@ -47,12 +47,19 @@ test_roundtrip oct_signed -DBASE_HEX -DSIGN="signed"
test_roundtrip bin_unsigned -DBASE_HEX -DSIGN=""
test_roundtrip bin_signed -DBASE_HEX -DSIGN="signed"
../../yosys -p "read_verilog always_full.v; write_cxxrtl -print-output std::cerr yosys-always_full.cc"
${CC:-gcc} -std=c++11 -o yosys-always_full -I../.. always_full_tb.cc -lstdc++
./yosys-always_full 2>yosys-always_full.log
iverilog -o iverilog-always_full always_full.v always_full_tb.v
./iverilog-always_full | awk '/<<<BEGIN>>>/,/<<<END>>>/ {print $0}' >iverilog-always_full.log
diff iverilog-always_full.log yosys-always_full.log
test_cxxrtl () {
local subtest=$1; shift
../../yosys -p "read_verilog ${subtest}.v; write_cxxrtl -print-output std::cerr yosys-${subtest}.cc"
${CC:-gcc} -std=c++11 -o yosys-${subtest} -I../.. ${subtest}_tb.cc -lstdc++
./yosys-${subtest} 2>yosys-${subtest}.log
iverilog -o iverilog-${subtest} ${subtest}.v ${subtest}_tb.v
./iverilog-${subtest} |grep -v '\$finish called' >iverilog-${subtest}.log
diff iverilog-${subtest}.log yosys-${subtest}.log
}
test_cxxrtl always_full
test_cxxrtl always_comb
../../yosys -p "read_verilog display_lm.v" >yosys-display_lm.log
../../yosys -p "read_verilog display_lm.v; write_cxxrtl yosys-display_lm.cc"