2 * yosys -- Yosys Open SYnthesis Suite
4 * Copyright (C) 2019 Miodrag Milanovic <miodrag@symbioticeda.com>
5 * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 #include "kernel/yosys.h"
22 #include "kernel/sigtools.h"
25 PRIVATE_NAMESPACE_BEGIN
27 static void handle_gbufs(Module
*module
)
29 SigMap
sigmap(module
);
31 pool
<SigBit
> clk_bits
;
32 dict
<SigBit
, SigBit
> rewrite_bits
;
33 vector
<pair
<Cell
*, SigBit
>> pad_bits
;
35 for (auto cell
: module
->cells())
37 if (cell
->type
== "\\EFX_FF") {
38 for (auto bit
: sigmap(cell
->getPort("\\CLK")))
41 if (cell
->type
== "\\EFX_RAM_5K") {
42 for (auto bit
: sigmap(cell
->getPort("\\RCLK")))
44 for (auto bit
: sigmap(cell
->getPort("\\WCLK")))
49 for (auto wire
: vector
<Wire
*>(module
->wires()))
51 if (!wire
->port_input
)
54 for (int index
= 0; index
< GetSize(wire
); index
++)
56 SigBit
bit(wire
, index
);
57 SigBit canonical_bit
= sigmap(bit
);
59 if (!clk_bits
.count(canonical_bit
))
62 Cell
*c
= module
->addCell(NEW_ID
, "\\EFX_GBUFCE");
63 SigBit new_bit
= module
->addWire(NEW_ID
);
64 c
->setParam("\\CE_POLARITY", State::S1
);
65 c
->setPort("\\O", new_bit
);
66 c
->setPort("\\CE", State::S1
);
67 pad_bits
.push_back(make_pair(c
, bit
));
68 rewrite_bits
[canonical_bit
] = new_bit
;
70 log("Added %s cell %s for port bit %s.\n", log_id(c
->type
), log_id(c
), log_signal(bit
));
74 auto rewrite_function
= [&](SigSpec
&s
) {
76 SigBit canonical_bit
= sigmap(bit
);
77 if (rewrite_bits
.count(canonical_bit
))
78 bit
= rewrite_bits
.at(canonical_bit
);
82 module
->rewrite_sigspecs(rewrite_function
);
84 for (auto &it
: pad_bits
)
85 it
.first
->setPort("\\I", it
.second
);
88 struct EfinixGbufPass
: public Pass
{
89 EfinixGbufPass() : Pass("efinix_gbuf", "Efinix: insert global clock buffers") { }
90 void help() YS_OVERRIDE
92 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
94 log(" efinix_gbuf [options] [selection]\n");
96 log("Add Efinix global clock buffers to top module as needed.\n");
99 void execute(std::vector
<std::string
> args
, RTLIL::Design
*design
) YS_OVERRIDE
101 log_header(design
, "Executing efinix_gbuf pass (insert global clock buffers).\n");
104 for (argidx
= 1; argidx
< args
.size(); argidx
++)
108 extra_args(args
, argidx
, design
);
110 Module
*module
= design
->top_module();
112 if (module
== nullptr)
113 log_cmd_error("No top module found.\n");
115 handle_gbufs(module
);
119 PRIVATE_NAMESPACE_END