Skip to content

Commit 1cf8e7c

Browse files
committed
add ioff inference for qlf_k6n10f
1 parent 3d35f36 commit 1cf8e7c

File tree

4 files changed

+187
-2
lines changed

4 files changed

+187
-2
lines changed

techlibs/quicklogic/Makefile.inc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ OBJS += techlibs/quicklogic/ql_bram_merge.o
66
OBJS += techlibs/quicklogic/ql_bram_types.o
77
OBJS += techlibs/quicklogic/ql_dsp_simd.o
88
OBJS += techlibs/quicklogic/ql_dsp_io_regs.o
9+
OBJS += techlibs/quicklogic/ql_ioff.o
910

1011
# --------------------------------------
1112

@@ -40,4 +41,4 @@ $(eval $(call add_share_file,share/quicklogic/qlf_k6n10f,techlibs/quicklogic/qlf
4041
$(eval $(call add_share_file,share/quicklogic/qlf_k6n10f,techlibs/quicklogic/qlf_k6n10f/dsp_final_map.v))
4142
$(eval $(call add_share_file,share/quicklogic/qlf_k6n10f,techlibs/quicklogic/qlf_k6n10f/TDP18K_FIFO.v))
4243
$(eval $(call add_share_file,share/quicklogic/qlf_k6n10f,techlibs/quicklogic/qlf_k6n10f/ufifo_ctl.v))
43-
$(eval $(call add_share_file,share/quicklogic/qlf_k6n10f,techlibs/quicklogic/qlf_k6n10f/sram1024x18_mem.v))
44+
$(eval $(call add_share_file,share/quicklogic/qlf_k6n10f,techlibs/quicklogic/qlf_k6n10f/sram1024x18_mem.v))

techlibs/quicklogic/ql_ioff.cc

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
#include "kernel/log.h"
2+
#include "kernel/modtools.h"
3+
#include "kernel/register.h"
4+
#include "kernel/rtlil.h"
5+
6+
USING_YOSYS_NAMESPACE
7+
PRIVATE_NAMESPACE_BEGIN
8+
9+
struct QlIoffPass : public Pass {
10+
QlIoffPass() : Pass("ql_ioff", "Infer I/O FFs for qlf_k6n10f architecture") {}
11+
12+
void help() override
13+
{
14+
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
15+
log("\n");
16+
log(" ql_ioff [selection]\n");
17+
log("\n");
18+
log("This pass promotes qlf_k6n10f registers directly connected to a top-level I/O\n");
19+
log("port to I/O FFs.\n");
20+
log("\n");
21+
}
22+
23+
void execute(std::vector<std::string>, RTLIL::Design *design) override
24+
{
25+
log_header(design, "Executing QL_IOFF pass.\n");
26+
27+
ModWalker modwalker(design);
28+
Module *module = design->top_module();
29+
if (!module)
30+
return;
31+
modwalker.setup(module);
32+
pool<RTLIL::Cell *> cells_to_replace;
33+
for (auto cell : module->selected_cells()) {
34+
if (cell->type.in(ID(dffsre), ID(sdffsre))) {
35+
bool e_const = cell->getPort(ID::E).is_fully_ones();
36+
bool r_const = cell->getPort(ID::R).is_fully_ones();
37+
bool s_const = cell->getPort(ID::S).is_fully_ones();
38+
39+
if (!(e_const && r_const && s_const))
40+
continue;
41+
42+
auto d_sig = modwalker.sigmap(cell->getPort(ID::D));
43+
if (d_sig.is_wire() && d_sig.as_wire()->port_input) {
44+
log_debug("Cell %s is potentially eligible for promotion to input IOFF.\n", cell->name.c_str());
45+
// check that d_sig has no other consumers
46+
if (GetSize(d_sig) != 1) continue;
47+
pool<ModWalker::PortBit> portbits;
48+
modwalker.get_consumers(portbits, d_sig[0]);
49+
if (GetSize(portbits) > 1) {
50+
log_debug("not promoting: d_sig has other consumers\n");
51+
continue;
52+
}
53+
cells_to_replace.insert(cell);
54+
continue; // no need to check Q if we already put it on the list
55+
}
56+
auto q_sig = modwalker.sigmap(cell->getPort(ID::Q));
57+
if (q_sig.is_wire() && q_sig.as_wire()->port_output) {
58+
log_debug("Cell %s is potentially eligible for promotion to output IOFF.\n", cell->name.c_str());
59+
// check that q_sig has no other consumers
60+
if (GetSize(q_sig) != 1) continue;
61+
pool<ModWalker::PortBit> portbits;
62+
modwalker.get_consumers(portbits, q_sig[0]);
63+
if (GetSize(portbits) > 0) {
64+
log_debug("not promoting: q_sig has other consumers\n");
65+
continue;
66+
}
67+
cells_to_replace.insert(cell);
68+
}
69+
}
70+
}
71+
72+
for (auto cell : cells_to_replace) {
73+
log("Promoting register %s to IOFF.\n", log_signal(cell->getPort(ID::Q)));
74+
cell->type = ID(dff);
75+
cell->unsetPort(ID::E);
76+
cell->unsetPort(ID::R);
77+
cell->unsetPort(ID::S);
78+
}
79+
}
80+
} QlIoffPass;
81+
82+
PRIVATE_NAMESPACE_END

techlibs/quicklogic/synth_quicklogic.cc

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ struct SynthQuickLogicPass : public ScriptPass {
7878
}
7979

8080
string top_opt, blif_file, edif_file, family, currmodule, verilog_file, lib_path;
81-
bool abc9, inferAdder, nobram, bramTypes, dsp;
81+
bool abc9, inferAdder, nobram, bramTypes, dsp, ioff;
8282

8383
void clear_flags() override
8484
{
@@ -94,6 +94,7 @@ struct SynthQuickLogicPass : public ScriptPass {
9494
bramTypes = false;
9595
lib_path = "+/quicklogic/";
9696
dsp = true;
97+
ioff = true;
9798
}
9899

99100
void set_scratchpad_defaults(RTLIL::Design *design) {
@@ -158,6 +159,10 @@ struct SynthQuickLogicPass : public ScriptPass {
158159
dsp = false;
159160
continue;
160161
}
162+
if (args[argidx] == "-noioff") {
163+
ioff = false;
164+
continue;
165+
}
161166
break;
162167
}
163168
extra_args(args, argidx, design);
@@ -328,6 +333,12 @@ struct SynthQuickLogicPass : public ScriptPass {
328333
run("clean");
329334
run("opt_lut");
330335
}
336+
337+
if (check_label("iomap", "(for qlf_k6n10f)") && (family == "qlf_k6n10f" || help_mode)) {
338+
if (ioff || help_mode) {
339+
run("ql_ioff", "(unless -noioff)");
340+
}
341+
}
331342

332343
if (check_label("check")) {
333344
run("autoname");
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
# test: acceptable for output IOFF promotion
2+
read_verilog <<EOF
3+
module top (input clk, input a, output reg o);
4+
always @(posedge clk) begin
5+
o <= ~a;
6+
end
7+
endmodule
8+
EOF
9+
synth_quicklogic -family qlf_k6n10f -top top
10+
select -assert-count 1 t:dff
11+
12+
design -reset
13+
# test: acceptable for input IOFF promotion
14+
read_verilog <<EOF
15+
module top (input clk, input a, output o);
16+
reg r;
17+
always @(posedge clk) begin
18+
r <= a;
19+
end
20+
assign o = ~r;
21+
endmodule
22+
EOF
23+
synth_quicklogic -family qlf_k6n10f -top top
24+
select -assert-count 1 t:dff
25+
26+
design -reset
27+
# test: acceptable for either IOFF promotion
28+
read_verilog <<EOF
29+
module top (input clk, input a, output reg o);
30+
always @(posedge clk) begin
31+
o <= a;
32+
end
33+
endmodule
34+
EOF
35+
synth_quicklogic -family qlf_k6n10f -top top
36+
select -assert-count 1 t:dff
37+
38+
design -reset
39+
# test: not acceptable for output IOFF promotion: output signal is used
40+
read_verilog <<EOF
41+
module top (input clk, input a, output reg o);
42+
always @(posedge clk) begin
43+
o <= ~a | o;
44+
end
45+
endmodule
46+
EOF
47+
synth_quicklogic -family qlf_k6n10f -top top
48+
select -assert-count 0 t:dff
49+
50+
design -reset
51+
# test: not acceptable for input IOFF promotion: input signal is used
52+
read_verilog <<EOF
53+
module top (input clk, input a, output o, p);
54+
reg r;
55+
always @(posedge clk) begin
56+
r <= a;
57+
end
58+
assign o = ~r;
59+
assign p = ~a;
60+
endmodule
61+
EOF
62+
synth_quicklogic -family qlf_k6n10f -top top
63+
select -assert-count 0 t:dff
64+
65+
design -reset
66+
# test: not acceptable for IOFF promotion: FF has reset
67+
read_verilog <<EOF
68+
module top (input clk, input rst, input a, output reg o);
69+
always @(posedge clk) begin
70+
if (rst)
71+
o <= 1'b0;
72+
else
73+
o <= a;
74+
end
75+
endmodule
76+
EOF
77+
synth_quicklogic -family qlf_k6n10f -top top
78+
select -assert-count 0 t:dff
79+
80+
design -reset
81+
# test: not acceptable for IOFF promotion: FF has enable
82+
read_verilog <<EOF
83+
module top (input clk, input en, input a, output reg o);
84+
always @(posedge clk) begin
85+
if (en)
86+
o <= a;
87+
end
88+
endmodule
89+
EOF
90+
synth_quicklogic -family qlf_k6n10f -top top
91+
select -assert-count 0 t:dff

0 commit comments

Comments
 (0)