Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: azonenberg/yosys
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: b5c15636c559^
Choose a base ref
...
head repository: azonenberg/yosys
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 3fc1b9f3fdd7
Choose a head ref
  • 3 commits
  • 5 files changed
  • 1 contributor

Commits on Aug 29, 2017

  1. Refactoring: Renamed greenpak4_counters pass to extract_counter, move…

    …d it to techmap/ since it's going to become a generic pass
    azonenberg committed Aug 29, 2017
    Copy the full SHA
    b5c1563 View commit details
  2. Copy the full SHA
    46b01f0 View commit details
  3. Finished refactoring counter extraction to be nice and generic. Imple…

    …mented techmapping from $__COUNT_ to GP_COUNTx cells.
    azonenberg committed Aug 29, 2017
    Copy the full SHA
    3fc1b9f View commit details
1 change: 1 addition & 0 deletions passes/techmap/Makefile.inc
Original file line number Diff line number Diff line change
@@ -17,6 +17,7 @@ OBJS += passes/techmap/iopadmap.o
OBJS += passes/techmap/hilomap.o
OBJS += passes/techmap/extract.o
OBJS += passes/techmap/extract_fa.o
OBJS += passes/techmap/extract_counter.o
OBJS += passes/techmap/extract_reduce.o
OBJS += passes/techmap/alumacc.o
OBJS += passes/techmap/dff2dffe.o
Original file line number Diff line number Diff line change
@@ -103,15 +103,22 @@ struct CounterExtraction
};

//attempt to extract a counter centered on the given adder cell
int greenpak4_counters_tryextract(ModIndex& index, Cell *cell, CounterExtraction& extract)
//For now we only support DOWN counters.
//TODO: up/down support
int counter_tryextract(
ModIndex& index,
Cell *cell,
CounterExtraction& extract,
pool<RTLIL::IdString>& parallel_cells,
int maxwidth)
{
SigMap& sigmap = index.sigmap;

//GreenPak does not support counters larger than 14 bits so immediately skip anything bigger
//TODO: infer cascaded counters?
//A counter with less than 2 bits makes no sense
//TODO: configurable min threshold
int a_width = cell->getParam("\\A_WIDTH").as_int();
extract.width = a_width;
if(a_width > 14)
if( (a_width < 2) || (a_width > maxwidth) )
return 1;

//Second input must be a single bit
@@ -221,40 +228,43 @@ int greenpak4_counters_tryextract(ModIndex& index, Cell *cell, CounterExtraction
pool<Cell*> cnout_loads = get_other_cells(cnout, index, count_reg);
if(cnout_loads.size() > 2)
{
//It's OK to have other loads iff they go to a DAC or DCMP (these are POUT)
for(auto c : cnout_loads)
//If we specified a limited set of cells for parallel output, check that we only drive them
if(!parallel_cells.empty())
{
if(c == underflow_inv)
continue;
if(c == cell)
continue;

//If the cell is not a DAC or DCMP, complain
if( (c->type != "\\GP_DCMP") && (c->type != "\\GP_DAC") )
return 17;

//Figure out what port(s) are driven by it
//TODO: this can probably be done more efficiently w/o multiple iterations over our whole net?
RTLIL::IdString portname;
for(auto b : qport)
for(auto c : cnout_loads)
{
pool<ModIndex::PortInfo> ports = index.query_ports(b);
for(auto x : ports)
if(c == underflow_inv)
continue;
if(c == cell)
continue;

//Make sure we're in the whitelist
if( parallel_cells.find(c->type) == parallel_cells.end())
return 17;

//Figure out what port(s) are driven by it
//TODO: this can probably be done more efficiently w/o multiple iterations over our whole net?
RTLIL::IdString portname;
for(auto b : qport)
{
if(x.cell != c)
continue;
if(portname == "")
portname = x.port;

//somehow our counter output is going to multiple ports
//this makes no sense, don't allow inference
else if(portname != x.port)
return 17;
pool<ModIndex::PortInfo> ports = index.query_ports(b);
for(auto x : ports)
{
if(x.cell != c)
continue;
if(portname == "")
portname = x.port;

//somehow our counter output is going to multiple ports
//this makes no sense, don't allow inference
else if(portname != x.port)
return 17;
}
}
}

//Save the other loads
extract.pouts.insert(ModIndex::PortInfo(c, portname, 0));
//Save the other loads
extract.pouts.insert(ModIndex::PortInfo(c, portname, 0));
}
}
}
if(!is_full_bus(cnout, index, count_reg, "\\Q", underflow_inv, "\\A", true))
@@ -276,12 +286,14 @@ int greenpak4_counters_tryextract(ModIndex& index, Cell *cell, CounterExtraction
return 0;
}

void greenpak4_counters_worker(
void counter_worker(
ModIndex& index,
Cell *cell,
unsigned int& total_counters,
pool<Cell*>& cells_to_remove,
pool<pair<Cell*, string>>& cells_to_rename)
pool<pair<Cell*, string>>& cells_to_rename,
pool<RTLIL::IdString>& parallel_cells,
int maxwidth)
{
SigMap& sigmap = index.sigmap;

@@ -328,7 +340,7 @@ void greenpak4_counters_worker(

//Attempt to extract a counter
CounterExtraction extract;
int reason = greenpak4_counters_tryextract(index, cell, extract);
int reason = counter_tryextract(index, cell, extract, parallel_cells, maxwidth);

//Nonzero code - we could not find a matchable counter.
//Do nothing, unless extraction was forced in which case give an error
@@ -337,7 +349,7 @@ void greenpak4_counters_worker(
static const char* reasons[24]=
{
"no problem", //0
"counter is larger than 14 bits", //1
"counter is too large/small", //1
"counter does not count by one", //2
"counter uses signed math", //3
"counter does not count by one", //4
@@ -353,7 +365,7 @@ void greenpak4_counters_worker(
"Mux output is used outside counter", //14
"Counter reg is not DFF/ADFF", //15
"Counter input is not full bus", //16
"Count register is used outside counter, but not by a DCMP or DAC", //17
"Count register is used outside counter, but not by an allowed cell", //17
"Register output is not full bus", //18
"Register output is not full bus", //19
"No init value found", //20
@@ -372,13 +384,8 @@ void greenpak4_counters_worker(
return;
}

//Figure out the final cell type based on the counter size
string celltype = "\\GP_COUNT8";
if(extract.width > 8)
celltype = "\\GP_COUNT14";

//Get new cell name
string countname = string("$auto$GP_COUNTx$") + log_id(extract.rwire->name.str());
string countname = string("$auto$COUNTx$") + log_id(extract.rwire->name.str());

//Log it
total_counters ++;
@@ -411,7 +418,7 @@ void greenpak4_counters_worker(
cell->unsetParam("\\Y_WIDTH");

//Change the cell type
cell->type = celltype;
cell->type = "$__COUNT_";

//Hook up resets
if(extract.has_reset)
@@ -427,12 +434,19 @@ void greenpak4_counters_worker(
}

//Hook up other stuff
cell->setParam("\\CLKIN_DIVIDE", RTLIL::Const(1));
//cell->setParam("\\CLKIN_DIVIDE", RTLIL::Const(1));
cell->setParam("\\COUNT_TO", RTLIL::Const(extract.count_value));

cell->setParam("\\WIDTH", RTLIL::Const(extract.width));
cell->setPort("\\CLK", extract.clk);
cell->setPort("\\OUT", extract.outsig);

//Hook up hard-wired ports (for now CE and up/=down are not supported), default to no parallel output
cell->setParam("\\HAS_POUT", RTLIL::Const(0));
cell->setParam("\\HAS_CE", RTLIL::Const(0));
cell->setParam("\\DIRECTION", RTLIL::Const("DOWN"));
cell->setPort("\\CE", RTLIL::Const(1));
cell->setPort("\\UP", RTLIL::Const(1));

//Hook up any parallel outputs
for(auto load : extract.pouts)
{
@@ -444,6 +458,7 @@ void greenpak4_counters_worker(
//Connect it to our parallel output
//(this is OK to do more than once b/c they all go to the same place)
cell->setPort("\\POUT", sig);
cell->setParam("\\HAS_POUT", RTLIL::Const(1));
}

//Delete the cells we've replaced (let opt_clean handle deleting the now-redundant wires)
@@ -455,29 +470,64 @@ void greenpak4_counters_worker(
cells_to_rename.insert(pair<Cell*, string>(cell, countname));
}

struct Greenpak4CountersPass : public Pass {
Greenpak4CountersPass() : Pass("greenpak4_counters", "Extract GreenPak4 counter cells") { }
struct ExtractCounterPass : public Pass {
ExtractCounterPass() : Pass("extract_counter", "Extract GreenPak4 counter cells") { }
virtual void help()
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
log(" greenpak4_counters [options] [selection]\n");
log(" extract_counter [options] [selection]\n");
log("\n");
log("This pass converts non-resettable or async resettable down counters to\n");
log("counter cells. Use a target-specific 'techmap' map file to convert those cells\n");
log("to the actual target cells.\n");
log("\n");
log(" -maxwidth N\n");
log(" Only extract counters up to N bits wide\n");
log(" -pout X,Y,...\n");
log(" Only allow parallel output from the counter to the listed cell types\n");
log(" (if not specified, parallel outputs are not restricted)\n");
log("\n");
log("This pass converts non-resettable or async resettable down counters to GreenPak4\n");
log("counter cells (All other GreenPak4 counter modes must be instantiated manually.)\n");
log("\n");
}
virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
{
log_header(design, "Executing GREENPAK4_COUNTERS pass (mapping counters to hard IP blocks).\n");
log_header(design, "Executing EXTRACT_COUNTER pass (find counters in netlist).\n");

int maxwidth = 64;
size_t argidx;
pool<RTLIL::IdString> parallel_cells;
for (argidx = 1; argidx < args.size(); argidx++)
{
// if (args[argidx] == "-v") {
// continue;
// }
break;
if (args[argidx] == "-pout")
{
if(argidx + 1 >= args.size())
{
log_error("extract_counter -pout requires an argument\n");
return;
}

std::string pouts = args[++argidx];
std::string tmp;
for(size_t i=0; i<pouts.length(); i++)
{
if(pouts[i] == ',')
{
parallel_cells.insert(RTLIL::IdString(tmp));
tmp = "";
}
else
tmp += pouts[i];
}
parallel_cells.insert(RTLIL::IdString(tmp));
continue;
}

if (args[argidx] == "-maxwidth" && argidx+1 < args.size())
{
maxwidth = atoi(args[++argidx].c_str());
continue;
}
}
extra_args(args, argidx, design);

@@ -490,7 +540,7 @@ struct Greenpak4CountersPass : public Pass {

ModIndex index(module);
for (auto cell : module->selected_cells())
greenpak4_counters_worker(index, cell, total_counters, cells_to_remove, cells_to_rename);
counter_worker(index, cell, total_counters, cells_to_remove, cells_to_rename, parallel_cells, maxwidth);

for(auto cell : cells_to_remove)
{
@@ -508,6 +558,6 @@ struct Greenpak4CountersPass : public Pass {
if(total_counters)
log("Extracted %u counters\n", total_counters);
}
} Greenpak4CountersPass;
} ExtractCounterPass;

PRIVATE_NAMESPACE_END
1 change: 0 additions & 1 deletion techlibs/greenpak4/Makefile.inc
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@

OBJS += techlibs/greenpak4/synth_greenpak4.o
OBJS += techlibs/greenpak4/greenpak4_counters.o
OBJS += techlibs/greenpak4/greenpak4_dffinv.o

$(eval $(call add_share_file,share/greenpak4,techlibs/greenpak4/cells_latch.v))
68 changes: 68 additions & 0 deletions techlibs/greenpak4/cells_map.v
Original file line number Diff line number Diff line change
@@ -144,3 +144,71 @@ module \$lut (A, Y);
end
endgenerate
endmodule

module \$__COUNT_ (CE, CLK, OUT, POUT, RST, UP);

input wire CE;
input wire CLK;
output reg OUT;
output reg[WIDTH-1:0] POUT;
input wire RST;
input wire UP;

parameter COUNT_TO = 1;
parameter RESET_MODE = "RISING";
parameter HAS_POUT = 0;
parameter HAS_CE = 0;
parameter WIDTH = 8;
parameter DIRECTION = "DOWN";

//If we have a CE, or DIRECTION other than DOWN fail... GP_COUNTx_ADV is not supported yet
if(HAS_CE || (DIRECTION != "DOWN") ) begin
initial begin
$display("ERROR: \$__COUNT__ support for GP_COUNTx_ADV is not yet implemented. This counter should never have been extracted (bug in extract_counter pass?).");
$finish;
end
end

//If counter is more than 14 bits wide, complain (also shouldn't happen)
else if(WIDTH > 14) begin
initial begin
$display("ERROR: \$__COUNT__ support for cascaded counters is not yet implemented. This counter should never have been extracted (bug in extract_counter pass?).");
$finish;
end
end

//If counter is more than 8 bits wide and has parallel output, we have a problem
else if(WIDTH > 8 && HAS_POUT) begin
initial begin
$display("ERROR: \$__COUNT__ support for 9-14 bit counters with parallel output is not yet implemented. This counter should never have been extracted (bug in extract_counter pass?).");
$finish;
end
end

//Looks like a legal counter! Do something with it
else if(WIDTH <= 8) begin
GP_COUNT8 #(
.COUNT_TO(COUNT_TO),
.RESET_MODE(RESET_MODE),
.CLKIN_DIVIDE(1)
) _TECHMAP_REPLACE_ (
.CLK(CLK),
.RST(RST),
.OUT(OUT),
.POUT(POUT)
);
end

else begin
GP_COUNT14 #(
.COUNT_TO(COUNT_TO),
.RESET_MODE(RESET_MODE),
.CLKIN_DIVIDE(1)
) _TECHMAP_REPLACE_ (
.CLK(CLK),
.RST(RST),
.OUT(OUT)
);
end

endmodule
2 changes: 1 addition & 1 deletion techlibs/greenpak4/synth_greenpak4.cc
Original file line number Diff line number Diff line change
@@ -155,7 +155,7 @@ struct SynthGreenPAK4Pass : public ScriptPass

if (check_label("fine"))
{
run("greenpak4_counters");
run("extract_counter -pout \\GP_DCMP,\\GP_DAC -maxwidth 14");
run("clean");
run("opt -fast -mux_undef -undriven -fine");
run("memory_map");