Skip to content

Commit

Permalink
add ioff inference for qlf_k6n10f
Browse files Browse the repository at this point in the history
  • Loading branch information
nakengelhardt committed Jan 24, 2025
1 parent 3d35f36 commit 1e6129c
Show file tree
Hide file tree
Showing 4 changed files with 173 additions and 2 deletions.
3 changes: 2 additions & 1 deletion techlibs/quicklogic/Makefile.inc
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ OBJS += techlibs/quicklogic/ql_bram_merge.o
OBJS += techlibs/quicklogic/ql_bram_types.o
OBJS += techlibs/quicklogic/ql_dsp_simd.o
OBJS += techlibs/quicklogic/ql_dsp_io_regs.o
OBJS += techlibs/quicklogic/ql_ioff.o

# --------------------------------------

Expand Down Expand Up @@ -40,4 +41,4 @@ $(eval $(call add_share_file,share/quicklogic/qlf_k6n10f,techlibs/quicklogic/qlf
$(eval $(call add_share_file,share/quicklogic/qlf_k6n10f,techlibs/quicklogic/qlf_k6n10f/dsp_final_map.v))
$(eval $(call add_share_file,share/quicklogic/qlf_k6n10f,techlibs/quicklogic/qlf_k6n10f/TDP18K_FIFO.v))
$(eval $(call add_share_file,share/quicklogic/qlf_k6n10f,techlibs/quicklogic/qlf_k6n10f/ufifo_ctl.v))
$(eval $(call add_share_file,share/quicklogic/qlf_k6n10f,techlibs/quicklogic/qlf_k6n10f/sram1024x18_mem.v))
$(eval $(call add_share_file,share/quicklogic/qlf_k6n10f,techlibs/quicklogic/qlf_k6n10f/sram1024x18_mem.v))
71 changes: 71 additions & 0 deletions techlibs/quicklogic/ql_ioff.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#include "kernel/log.h"
#include "kernel/modtools.h"
#include "kernel/register.h"
#include "kernel/rtlil.h"

USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN

struct QlIoffPass : public Pass {
QlIoffPass() : Pass("ql_ioff", "Infer I/O FFs for qlf_k6n10f architecture") {}

void execute(std::vector<std::string>, RTLIL::Design *design) override
{
log_header(design, "Executing QL_IOFF pass.\n");

ModWalker modwalker(design);
Module *module = design->top_module();
if (!module)
return;
modwalker.setup(module);
pool<RTLIL::Cell *> cells_to_replace;
for (auto cell : module->selected_cells()) {
if (cell->type.in(ID(dffsre), ID(sdffsre))) {
bool e_const = cell->getPort(ID::E).is_fully_const();
bool r_const = cell->getPort(ID::R).is_fully_const();
bool s_const = cell->getPort(ID::S).is_fully_const();

if (!(e_const && r_const && s_const))
continue;

auto d_sig = modwalker.sigmap(cell->getPort(ID::D));
if (d_sig.is_wire() && d_sig.as_wire()->port_input) {
log_debug("Cell %s is potentially eligible for promotion to input IOFF.\n", cell->name.c_str());
// check that d_sig has no other consumers
if (GetSize(d_sig) != 1) continue;
pool<ModWalker::PortBit> portbits;
modwalker.get_consumers(portbits, d_sig[0]);
if (GetSize(portbits) > 1) {
log_debug("not promoting: d_sig has other consumers\n");
continue;
}
cells_to_replace.insert(cell);
continue; // no need to check Q if we already put it on the list
}
auto q_sig = modwalker.sigmap(cell->getPort(ID::Q));
if (q_sig.is_wire() && q_sig.as_wire()->port_output) {
log_debug("Cell %s is potentially eligible for promotion to output IOFF.\n", cell->name.c_str());
// check that q_sig has no other consumers
if (GetSize(q_sig) != 1) continue;
pool<ModWalker::PortBit> portbits;
modwalker.get_consumers(portbits, q_sig[0]);
if (GetSize(portbits) > 0) {
log_debug("not promoting: q_sig has other consumers\n");
continue;
}
cells_to_replace.insert(cell);
}
}
}

for (auto cell : cells_to_replace) {
log("Promoting register %s to IOFF.\n", log_signal(cell->getPort(ID::Q)));
cell->type = ID(dff);
cell->unsetPort(ID::E);
cell->unsetPort(ID::R);
cell->unsetPort(ID::S);
}
}
} QlIoffPass;

PRIVATE_NAMESPACE_END
10 changes: 9 additions & 1 deletion techlibs/quicklogic/synth_quicklogic.cc
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ struct SynthQuickLogicPass : public ScriptPass {
}

string top_opt, blif_file, edif_file, family, currmodule, verilog_file, lib_path;
bool abc9, inferAdder, nobram, bramTypes, dsp;
bool abc9, inferAdder, nobram, bramTypes, dsp, ioff;

void clear_flags() override
{
Expand All @@ -94,6 +94,7 @@ struct SynthQuickLogicPass : public ScriptPass {
bramTypes = false;
lib_path = "+/quicklogic/";
dsp = true;
ioff = true;
}

void set_scratchpad_defaults(RTLIL::Design *design) {
Expand Down Expand Up @@ -158,6 +159,10 @@ struct SynthQuickLogicPass : public ScriptPass {
dsp = false;
continue;
}
if (args[argidx] == "-noioff") {
ioff = false;
continue;
}
break;
}
extra_args(args, argidx, design);
Expand Down Expand Up @@ -298,6 +303,9 @@ struct SynthQuickLogicPass : public ScriptPass {
run("techmap -map " + lib_path + family + "/ffs_map.v");
}
run("opt");
if (ioff || help_mode) {
run("ql_ioff", "(unless -noioff)");
}
}

if (check_label("map_luts", "(for pp3)") && (help_mode || family == "pp3")) {
Expand Down
91 changes: 91 additions & 0 deletions tests/arch/quicklogic/qlf_k6n10f/ioff.ys
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
# test: acceptable for output IOFF promotion
read_verilog <<EOF
module top (input clk, input a, output reg o);
always @(posedge clk) begin
o <= ~a;
end
endmodule
EOF
synth_quicklogic -family qlf_k6n10f -top top
select -assert-count 1 t:dff

design -reset
# test: acceptable for input IOFF promotion
read_verilog <<EOF
module top (input clk, input a, output o);
reg r;
always @(posedge clk) begin
r <= a;
end
assign o = ~r;
endmodule
EOF
synth_quicklogic -family qlf_k6n10f -top top
select -assert-count 1 t:dff

design -reset
# test: acceptable for either IOFF promotion
read_verilog <<EOF
module top (input clk, input a, output reg o);
always @(posedge clk) begin
o <= a;
end
endmodule
EOF
synth_quicklogic -family qlf_k6n10f -top top
select -assert-count 1 t:dff

design -reset
# test: not acceptable for output IOFF promotion: output signal is used
read_verilog <<EOF
module top (input clk, input a, output reg o);
always @(posedge clk) begin
o <= ~a | o;
end
endmodule
EOF
synth_quicklogic -family qlf_k6n10f -top top
select -assert-count 0 t:dff

design -reset
# test: not acceptable for input IOFF promotion: input signal is used
read_verilog <<EOF
module top (input clk, input a, output o, p);
reg r;
always @(posedge clk) begin
r <= a;
end
assign o = ~r;
assign p = ~a;
endmodule
EOF
synth_quicklogic -family qlf_k6n10f -top top
select -assert-count 0 t:dff

design -reset
# test: not acceptable for IOFF promotion: FF has reset
read_verilog <<EOF
module top (input clk, input rst, input a, output reg o);
always @(posedge clk) begin
if (rst)
o <= 1'b0;
else
o <= a;
end
endmodule
EOF
synth_quicklogic -family qlf_k6n10f -top top
select -assert-count 0 t:dff

design -reset
# test: not acceptable for IOFF promotion: FF has enable
read_verilog <<EOF
module top (input clk, input en, input a, output reg o);
always @(posedge clk) begin
if (en)
o <= a;
end
endmodule
EOF
synth_quicklogic -family qlf_k6n10f -top top
select -assert-count 0 t:dff

0 comments on commit 1e6129c

Please sign in to comment.