mirror of https://github.com/YosysHQ/yosys.git
add ioff inference for qlf_k6n10f
This commit is contained in:
parent
3d35f367cf
commit
1cf8e7c7db
|
@ -6,6 +6,7 @@ OBJS += techlibs/quicklogic/ql_bram_merge.o
|
||||||
OBJS += techlibs/quicklogic/ql_bram_types.o
|
OBJS += techlibs/quicklogic/ql_bram_types.o
|
||||||
OBJS += techlibs/quicklogic/ql_dsp_simd.o
|
OBJS += techlibs/quicklogic/ql_dsp_simd.o
|
||||||
OBJS += techlibs/quicklogic/ql_dsp_io_regs.o
|
OBJS += techlibs/quicklogic/ql_dsp_io_regs.o
|
||||||
|
OBJS += techlibs/quicklogic/ql_ioff.o
|
||||||
|
|
||||||
# --------------------------------------
|
# --------------------------------------
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,82 @@
|
||||||
|
#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 help() override
|
||||||
|
{
|
||||||
|
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
||||||
|
log("\n");
|
||||||
|
log(" ql_ioff [selection]\n");
|
||||||
|
log("\n");
|
||||||
|
log("This pass promotes qlf_k6n10f registers directly connected to a top-level I/O\n");
|
||||||
|
log("port to I/O FFs.\n");
|
||||||
|
log("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
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_ones();
|
||||||
|
bool r_const = cell->getPort(ID::R).is_fully_ones();
|
||||||
|
bool s_const = cell->getPort(ID::S).is_fully_ones();
|
||||||
|
|
||||||
|
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
|
|
@ -78,7 +78,7 @@ struct SynthQuickLogicPass : public ScriptPass {
|
||||||
}
|
}
|
||||||
|
|
||||||
string top_opt, blif_file, edif_file, family, currmodule, verilog_file, lib_path;
|
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
|
void clear_flags() override
|
||||||
{
|
{
|
||||||
|
@ -94,6 +94,7 @@ struct SynthQuickLogicPass : public ScriptPass {
|
||||||
bramTypes = false;
|
bramTypes = false;
|
||||||
lib_path = "+/quicklogic/";
|
lib_path = "+/quicklogic/";
|
||||||
dsp = true;
|
dsp = true;
|
||||||
|
ioff = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_scratchpad_defaults(RTLIL::Design *design) {
|
void set_scratchpad_defaults(RTLIL::Design *design) {
|
||||||
|
@ -158,6 +159,10 @@ struct SynthQuickLogicPass : public ScriptPass {
|
||||||
dsp = false;
|
dsp = false;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (args[argidx] == "-noioff") {
|
||||||
|
ioff = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
extra_args(args, argidx, design);
|
extra_args(args, argidx, design);
|
||||||
|
@ -329,6 +334,12 @@ struct SynthQuickLogicPass : public ScriptPass {
|
||||||
run("opt_lut");
|
run("opt_lut");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (check_label("iomap", "(for qlf_k6n10f)") && (family == "qlf_k6n10f" || help_mode)) {
|
||||||
|
if (ioff || help_mode) {
|
||||||
|
run("ql_ioff", "(unless -noioff)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (check_label("check")) {
|
if (check_label("check")) {
|
||||||
run("autoname");
|
run("autoname");
|
||||||
run("hierarchy -check");
|
run("hierarchy -check");
|
||||||
|
|
|
@ -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
|
Loading…
Reference in New Issue