mirror of https://github.com/YosysHQ/yosys.git
clkbufmap: improve input pad handling.
- allow inserting only the input pad cell - do not insert the usual buffer if the input pad already acts as a buffer
This commit is contained in:
parent
802671b22e
commit
32d2cc8c28
|
@ -34,33 +34,34 @@ void split_portname_pair(std::string &port1, std::string &port2)
|
|||
}
|
||||
|
||||
struct ClkbufmapPass : public Pass {
|
||||
ClkbufmapPass() : Pass("clkbufmap", "insert global buffers on clock networks") { }
|
||||
ClkbufmapPass() : Pass("clkbufmap", "insert clock buffers on clock networks") { }
|
||||
void help() override
|
||||
{
|
||||
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
||||
log("\n");
|
||||
log(" clkbufmap [options] [selection]\n");
|
||||
log("\n");
|
||||
log("Inserts global buffers between nets connected to clock inputs and their drivers.\n");
|
||||
log("Inserts clock buffers between nets connected to clock inputs and their drivers.\n");
|
||||
log("\n");
|
||||
log("In the absence of any selection, all wires without the 'clkbuf_inhibit'\n");
|
||||
log("attribute will be considered for global buffer insertion.\n");
|
||||
log("attribute will be considered for clock buffer insertion.\n");
|
||||
log("Alternatively, to consider all wires without the 'buffer_type' attribute set to\n");
|
||||
log("'none' or 'bufr' one would specify:\n");
|
||||
log(" 'w:* a:buffer_type=none a:buffer_type=bufr %%u %%d'\n");
|
||||
log("as the selection.\n");
|
||||
log("\n");
|
||||
log(" -buf <celltype> <portname_out>:<portname_in>\n");
|
||||
log(" Specifies the cell type to use for the global buffers\n");
|
||||
log(" Specifies the cell type to use for the clock buffers\n");
|
||||
log(" and its port names. The first port will be connected to\n");
|
||||
log(" the clock network sinks, and the second will be connected\n");
|
||||
log(" to the actual clock source. This option is required.\n");
|
||||
log(" to the actual clock source.\n");
|
||||
log("\n");
|
||||
log(" -inpad <celltype> <portname_out>:<portname_in>\n");
|
||||
log(" If specified, a PAD cell of the given type is inserted on\n");
|
||||
log(" clock nets that are also top module's inputs (in addition\n");
|
||||
log(" to the global buffer).\n");
|
||||
log(" to the clock buffer, if any).\n");
|
||||
log("\n");
|
||||
log("At least one of -buf or -inpad should be specified.\n");
|
||||
}
|
||||
|
||||
void module_queue(Design *design, Module *module, std::vector<Module *> &modules_sorted, pool<Module *> &modules_processed) {
|
||||
|
@ -78,7 +79,7 @@ struct ClkbufmapPass : public Pass {
|
|||
|
||||
void execute(std::vector<std::string> args, RTLIL::Design *design) override
|
||||
{
|
||||
log_header(design, "Executing CLKBUFMAP pass (inserting global clock buffers).\n");
|
||||
log_header(design, "Executing CLKBUFMAP pass (inserting clock buffers).\n");
|
||||
|
||||
std::string buf_celltype, buf_portname, buf_portname2;
|
||||
std::string inpad_celltype, inpad_portname, inpad_portname2;
|
||||
|
@ -109,8 +110,8 @@ struct ClkbufmapPass : public Pass {
|
|||
extra_args(args, argidx, design);
|
||||
}
|
||||
|
||||
if (buf_celltype.empty())
|
||||
log_error("The -buf option is required.\n");
|
||||
if (buf_celltype.empty() && inpad_celltype.empty())
|
||||
log_error("Either the -buf option or -inpad option is required.\n");
|
||||
|
||||
// Cell type, port name, bit index.
|
||||
pool<pair<IdString, pair<IdString, int>>> sink_ports;
|
||||
|
@ -118,6 +119,16 @@ struct ClkbufmapPass : public Pass {
|
|||
dict<pair<IdString, pair<IdString, int>>, pair<IdString, int>> inv_ports_out;
|
||||
dict<pair<IdString, pair<IdString, int>>, pair<IdString, int>> inv_ports_in;
|
||||
|
||||
// If true, use both ther -buf and -inpad cell for input ports that are clocks.
|
||||
bool buffer_inputs = true;
|
||||
|
||||
Module *inpad_mod = design->module(RTLIL::escape_id(inpad_celltype));
|
||||
if (inpad_mod) {
|
||||
Wire *buf_wire = inpad_mod->wire(RTLIL::escape_id(buf_portname));
|
||||
if (buf_wire && buf_wire->get_bool_attribute(ID::clkbuf_driver))
|
||||
buffer_inputs = false;
|
||||
}
|
||||
|
||||
// Process submodules before module using them.
|
||||
std::vector<Module *> modules_sorted;
|
||||
pool<Module *> modules_processed;
|
||||
|
@ -242,19 +253,30 @@ struct ClkbufmapPass : public Pass {
|
|||
// Clock network not yet buffered, driven by one of
|
||||
// our cells or a top-level input -- buffer it.
|
||||
|
||||
log("Inserting %s on %s.%s[%d].\n", buf_celltype.c_str(), log_id(module), log_id(wire), i);
|
||||
RTLIL::Cell *cell = module->addCell(NEW_ID, RTLIL::escape_id(buf_celltype));
|
||||
Wire *iwire = module->addWire(NEW_ID);
|
||||
cell->setPort(RTLIL::escape_id(buf_portname), mapped_wire_bit);
|
||||
cell->setPort(RTLIL::escape_id(buf_portname2), iwire);
|
||||
if (wire->port_input && !inpad_celltype.empty() && module->get_bool_attribute(ID::top)) {
|
||||
Wire *iwire = nullptr;
|
||||
RTLIL::Cell *cell = nullptr;
|
||||
bool is_input = wire->port_input && !inpad_celltype.empty() && module->get_bool_attribute(ID::top);
|
||||
if (!buf_celltype.empty() && (!is_input || buffer_inputs)) {
|
||||
log("Inserting %s on %s.%s[%d].\n", buf_celltype.c_str(), log_id(module), log_id(wire), i);
|
||||
cell = module->addCell(NEW_ID, RTLIL::escape_id(buf_celltype));
|
||||
iwire = module->addWire(NEW_ID);
|
||||
cell->setPort(RTLIL::escape_id(buf_portname), mapped_wire_bit);
|
||||
cell->setPort(RTLIL::escape_id(buf_portname2), iwire);
|
||||
}
|
||||
if (is_input) {
|
||||
log("Inserting %s on %s.%s[%d].\n", inpad_celltype.c_str(), log_id(module), log_id(wire), i);
|
||||
RTLIL::Cell *cell2 = module->addCell(NEW_ID, RTLIL::escape_id(inpad_celltype));
|
||||
cell2->setPort(RTLIL::escape_id(inpad_portname), iwire);
|
||||
if (iwire) {
|
||||
cell2->setPort(RTLIL::escape_id(inpad_portname), iwire);
|
||||
} else {
|
||||
cell2->setPort(RTLIL::escape_id(inpad_portname), mapped_wire_bit);
|
||||
cell = cell2;
|
||||
}
|
||||
iwire = module->addWire(NEW_ID);
|
||||
cell2->setPort(RTLIL::escape_id(inpad_portname2), iwire);
|
||||
}
|
||||
buffered_bits[mapped_wire_bit] = make_pair(cell, iwire);
|
||||
if (iwire)
|
||||
buffered_bits[mapped_wire_bit] = make_pair(cell, iwire);
|
||||
|
||||
if (wire->port_input) {
|
||||
input_bits.insert(i);
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
read_verilog <<EOT
|
||||
module clkbuf (input i, (* clkbuf_driver *) output o); endmodule
|
||||
module inbuf (input i, output o); endmodule
|
||||
module clkinbuf (input i, (* clkbuf_driver *) output o); endmodule
|
||||
module dff ((* clkbuf_sink *) input clk, input d, output q); endmodule
|
||||
module dffe ((* clkbuf_sink *) input c, input d, e, output q); endmodule
|
||||
module latch (input e, d, output q); endmodule
|
||||
|
@ -105,3 +107,80 @@ select -assert-count 0 w:clk1 %a %co t:clkbuf %i
|
|||
select -assert-count 0 w:clk2 %a %co t:clkbuf %i
|
||||
select -assert-count 0 top/t:clkbuf
|
||||
select -assert-count 2 sub/t:clkbuf
|
||||
|
||||
# ----------------------
|
||||
|
||||
design -load ref
|
||||
clkbufmap -buf clkbuf o:i -inpad inbuf o:i
|
||||
select -assert-count 3 top/t:clkbuf
|
||||
select -assert-count 3 sub/t:clkbuf
|
||||
select -assert-count 2 top/t:inbuf
|
||||
select -assert-count 0 sub/t:inbuf
|
||||
select -set clk1 w:clk1 %a %co t:inbuf %i
|
||||
select -assert-count 1 @clk1
|
||||
select -assert-count 1 @clk1 %x:+[o] %co t:clkbuf %i
|
||||
select -set clk1b @clk1 %x:+[o] %co t:clkbuf %i
|
||||
select -assert-count 1 @clk1b %x:+[o] %co c:s* %i
|
||||
select -assert-count 1 @clk1b %x:+[o] %co c:s0 %i
|
||||
select -set clk2 w:clk2 %a %co t:inbuf %i
|
||||
select -assert-count 1 @clk2
|
||||
select -assert-count 1 @clk2 %x:+[o] %co t:clkbuf %i
|
||||
select -set clk2b @clk2 %x:+[o] %co t:clkbuf %i
|
||||
select -assert-count 1 @clk2b %x:+[o] %co c:s* %i
|
||||
select -assert-count 1 @clk2b %x:+[o] %co c:s1 %i
|
||||
select -set clk5 w:clk5 %a %ci t:clkbuf %i
|
||||
select -assert-count 1 @clk5
|
||||
select -assert-count 1 @clk5 %x:+[o] %co c:s5 %i
|
||||
select -assert-count 1 @clk5 %x:+[i] %ci c:s3 %i
|
||||
select -set sclk4 w:sclk4 %a %ci t:clkbuf %i
|
||||
select -assert-count 1 @sclk4
|
||||
select -assert-count 1 @sclk4 %x:+[o] %co c:s11 %i
|
||||
select -assert-count 1 @sclk4 %x:+[i] %ci c:s7 %i
|
||||
select -set sclk8 w:sclk8 %a %ci t:clkbuf %i
|
||||
select -assert-count 1 @sclk8
|
||||
select -assert-count 1 @sclk8 %x:+[o] %co c:s13 %i
|
||||
select -assert-count 1 @sclk8 %x:+[i] %ci c:s12 %i
|
||||
|
||||
# ----------------------
|
||||
|
||||
design -load ref
|
||||
clkbufmap -inpad inbuf o:i
|
||||
select -assert-count 2 top/t:inbuf
|
||||
select -assert-count 0 sub/t:inbuf
|
||||
select -set clk1 w:clk1 %a %co t:inbuf %i
|
||||
select -assert-count 1 @clk1
|
||||
select -assert-count 1 @clk1 %x:+[o] %co c:s* %i
|
||||
select -assert-count 1 @clk1 %x:+[o] %co c:s0 %i
|
||||
select -set clk2 w:clk2 %a %co t:inbuf %i
|
||||
select -assert-count 1 @clk2
|
||||
select -assert-count 1 @clk2 %x:+[o] %co c:s* %i
|
||||
select -assert-count 1 @clk2 %x:+[o] %co c:s1 %i
|
||||
|
||||
# ----------------------
|
||||
|
||||
design -load ref
|
||||
clkbufmap -buf clkbuf o:i -inpad clkinbuf o:i
|
||||
select -assert-count 1 top/t:clkbuf
|
||||
select -assert-count 3 sub/t:clkbuf
|
||||
select -assert-count 2 top/t:clkinbuf
|
||||
select -assert-count 0 sub/t:clkinbuf
|
||||
select -set clk1 w:clk1 %a %co t:clkinbuf %i
|
||||
select -assert-count 1 @clk1
|
||||
select -assert-count 1 @clk1 %x:+[o] %co c:s* %i
|
||||
select -assert-count 1 @clk1 %x:+[o] %co c:s0 %i
|
||||
select -set clk2 w:clk2 %a %co t:clkinbuf %i
|
||||
select -assert-count 1 @clk2
|
||||
select -assert-count 1 @clk2 %x:+[o] %co c:s* %i
|
||||
select -assert-count 1 @clk2 %x:+[o] %co c:s1 %i
|
||||
select -set clk5 w:clk5 %a %ci t:clkbuf %i
|
||||
select -assert-count 1 @clk5
|
||||
select -assert-count 1 @clk5 %x:+[o] %co c:s5 %i
|
||||
select -assert-count 1 @clk5 %x:+[i] %ci c:s3 %i
|
||||
select -set sclk4 w:sclk4 %a %ci t:clkbuf %i
|
||||
select -assert-count 1 @sclk4
|
||||
select -assert-count 1 @sclk4 %x:+[o] %co c:s11 %i
|
||||
select -assert-count 1 @sclk4 %x:+[i] %ci c:s7 %i
|
||||
select -set sclk8 w:sclk8 %a %ci t:clkbuf %i
|
||||
select -assert-count 1 @sclk8
|
||||
select -assert-count 1 @sclk8 %x:+[o] %co c:s13 %i
|
||||
select -assert-count 1 @sclk8 %x:+[i] %ci c:s12 %i
|
||||
|
|
Loading…
Reference in New Issue