aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--kernel/log.cc1
-rw-r--r--passes/cmds/show.cc1
-rw-r--r--passes/cmds/splitcells.cc172
-rw-r--r--techlibs/gowin/cells_sim.v47
5 files changed, 169 insertions, 54 deletions
diff --git a/Makefile b/Makefile
index 51978eef9..2a05fcc50 100644
--- a/Makefile
+++ b/Makefile
@@ -141,7 +141,7 @@ LDLIBS += -lrt
endif
endif
-YOSYS_VER := 0.25+58
+YOSYS_VER := 0.25+60
# Note: We arrange for .gitcommit to contain the (short) commit hash in
# tarballs generated with git-archive(1) using .gitattributes. The git repo
diff --git a/kernel/log.cc b/kernel/log.cc
index 0092871f0..75a1ffb45 100644
--- a/kernel/log.cc
+++ b/kernel/log.cc
@@ -707,6 +707,7 @@ void log_check_expected()
if (item.second.current_count == item.second.expected_count) {
log_warn_regexes.clear();
log("Expected error pattern '%s' found !!!\n", item.first.c_str());
+ yosys_shutdown();
#ifdef EMSCRIPTEN
throw 0;
#elif defined(_MSC_VER)
diff --git a/passes/cmds/show.cc b/passes/cmds/show.cc
index b186e5db2..a7c77f96f 100644
--- a/passes/cmds/show.cc
+++ b/passes/cmds/show.cc
@@ -296,7 +296,6 @@ struct ShowWorker
code += stringf("x%d [ shape=record, style=rounded, label=\"%s\" ];\n", idx, label_string.c_str());
if (!port.empty()) {
currentColor = xorshift32(currentColor);
- log_warning("WIDTHLABEL %s %d\n", log_signal(sig), GetSize(sig));
if (driver)
code += stringf("%s:e -> x%d:w [arrowhead=odiamond, arrowtail=odiamond, dir=both, %s, %s];\n", port.c_str(), idx, nextColor(sig).c_str(), widthLabel(sig.size()).c_str());
else
diff --git a/passes/cmds/splitcells.cc b/passes/cmds/splitcells.cc
index de6df6142..82ed49074 100644
--- a/passes/cmds/splitcells.cc
+++ b/passes/cmds/splitcells.cc
@@ -68,70 +68,132 @@ struct SplitcellsWorker
int split(Cell *cell, const std::string &format)
{
- if (!cell->type.in("$and", "$mux", "$not", "$or", "$pmux", "$xnor", "$xor")) return 0;
+ if (cell->type.in("$and", "$mux", "$not", "$or", "$pmux", "$xnor", "$xor"))
+ {
+ SigSpec outsig = sigmap(cell->getPort(ID::Y));
+ if (GetSize(outsig) <= 1) return 0;
+
+ std::vector<int> slices;
+ slices.push_back(0);
+
+ int width = GetSize(outsig);
+ width = std::min(width, GetSize(cell->getPort(ID::A)));
+ if (cell->hasPort(ID::B))
+ width = std::min(width, GetSize(cell->getPort(ID::B)));
+
+ for (int i = 1; i < width; i++) {
+ auto &last_users = bit_users_db[outsig[slices.back()]];
+ auto &this_users = bit_users_db[outsig[i]];
+ if (last_users != this_users) slices.push_back(i);
+ }
+ if (GetSize(slices) <= 1) return 0;
+ slices.push_back(GetSize(outsig));
+
+ log("Splitting %s cell %s/%s into %d slices:\n", log_id(cell->type), log_id(module), log_id(cell), GetSize(slices)-1);
+ for (int i = 1; i < GetSize(slices); i++)
+ {
+ int slice_msb = slices[i]-1;
+ int slice_lsb = slices[i-1];
- SigSpec outsig = sigmap(cell->getPort(ID::Y));
- if (GetSize(outsig) <= 1) return 0;
+ IdString slice_name = module->uniquify(cell->name.str() + (slice_msb == slice_lsb ?
+ stringf("%c%d%c", format[0], slice_lsb, format[1]) :
+ stringf("%c%d%c%d%c", format[0], slice_msb, format[2], slice_lsb, format[1])));
+
+ Cell *slice = module->addCell(slice_name, cell);
+
+ auto slice_signal = [&](SigSpec old_sig) -> SigSpec {
+ SigSpec new_sig;
+ for (int i = 0; i < GetSize(old_sig); i += GetSize(outsig)) {
+ int offset = i+slice_lsb;
+ int length = std::min(GetSize(old_sig)-offset, slice_msb-slice_lsb+1);
+ new_sig.append(old_sig.extract(offset, length));
+ }
+ return new_sig;
+ };
+
+ slice->setPort(ID::A, slice_signal(slice->getPort(ID::A)));
+ if (slice->hasParam(ID::A_WIDTH))
+ slice->setParam(ID::A_WIDTH, GetSize(slice->getPort(ID::A)));
+
+ if (slice->hasPort(ID::B)) {
+ slice->setPort(ID::B, slice_signal(slice->getPort(ID::B)));
+ if (slice->hasParam(ID::B_WIDTH))
+ slice->setParam(ID::B_WIDTH, GetSize(slice->getPort(ID::B)));
+ }
- std::vector<int> slices;
- slices.push_back(0);
+ slice->setPort(ID::Y, slice_signal(slice->getPort(ID::Y)));
+ if (slice->hasParam(ID::Y_WIDTH))
+ slice->setParam(ID::Y_WIDTH, GetSize(slice->getPort(ID::Y)));
+ if (slice->hasParam(ID::WIDTH))
+ slice->setParam(ID::WIDTH, GetSize(slice->getPort(ID::Y)));
- int width = GetSize(outsig);
- width = std::min(width, GetSize(cell->getPort(ID::A)));
- if (cell->hasPort(ID::B))
- width = std::min(width, GetSize(cell->getPort(ID::B)));
+ log(" slice %d: %s => %s\n", i, log_id(slice_name), log_signal(slice->getPort(ID::Y)));
+ }
- for (int i = 1; i < width; i++) {
- auto &last_users = bit_users_db[outsig[slices.back()]];
- auto &this_users = bit_users_db[outsig[i]];
- if (last_users != this_users) slices.push_back(i);
+ module->remove(cell);
+ return GetSize(slices)-1;
}
- if (GetSize(slices) <= 1) return 0;
- slices.push_back(GetSize(outsig));
- log("Splitting %s cell %s/%s into %d slices:\n", log_id(cell->type), log_id(module), log_id(cell), GetSize(slices)-1);
- for (int i = 1; i < GetSize(slices); i++)
+ if (cell->type.in("$ff", "$dff", "$dffe", "$dffsr", "$dffsre", "$adff", "$adffe", "$aldffe",
+ "$sdff", "$sdffce", "$sdffe", "$dlatch", "$dlatchsr", "$adlatch"))
{
- int slice_msb = slices[i]-1;
- int slice_lsb = slices[i-1];
+ auto splitports = {ID::D, ID::Q, ID::AD, ID::SET, ID::CLR};
+ auto splitparams = {ID::ARST_VALUE, ID::SRST_VALUE};
+
+ SigSpec outsig = sigmap(cell->getPort(ID::Q));
+ if (GetSize(outsig) <= 1) return 0;
+ int width = GetSize(outsig);
+
+ std::vector<int> slices;
+ slices.push_back(0);
+
+ for (int i = 1; i < width; i++) {
+ auto &last_users = bit_users_db[outsig[slices.back()]];
+ auto &this_users = bit_users_db[outsig[i]];
+ if (last_users != this_users) slices.push_back(i);
+ }
+
+ if (GetSize(slices) <= 1) return 0;
+ slices.push_back(GetSize(outsig));
- IdString slice_name = module->uniquify(cell->name.str() + (slice_msb == slice_lsb ?
- stringf("%c%d%c", format[0], slice_lsb, format[1]) :
- stringf("%c%d%c%d%c", format[0], slice_msb, format[2], slice_lsb, format[1])));
+ log("Splitting %s cell %s/%s into %d slices:\n", log_id(cell->type), log_id(module), log_id(cell), GetSize(slices)-1);
+ for (int i = 1; i < GetSize(slices); i++)
+ {
+ int slice_msb = slices[i]-1;
+ int slice_lsb = slices[i-1];
- Cell *slice = module->addCell(slice_name, cell);
+ IdString slice_name = module->uniquify(cell->name.str() + (slice_msb == slice_lsb ?
+ stringf("%c%d%c", format[0], slice_lsb, format[1]) :
+ stringf("%c%d%c%d%c", format[0], slice_msb, format[2], slice_lsb, format[1])));
- auto slice_signal = [&](SigSpec old_sig) -> SigSpec {
- SigSpec new_sig;
- for (int i = 0; i < GetSize(old_sig); i += GetSize(outsig)) {
- int offset = i+slice_lsb;
- int length = std::min(GetSize(old_sig)-offset, slice_msb-slice_lsb+1);
- new_sig.append(old_sig.extract(offset, length));
+ Cell *slice = module->addCell(slice_name, cell);
+
+ for (IdString portname : splitports) {
+ if (slice->hasPort(portname)) {
+ SigSpec sig = slice->getPort(portname);
+ sig = sig.extract(slice_lsb, slice_msb-slice_lsb+1);
+ slice->setPort(portname, sig);
+ }
}
- return new_sig;
- };
- slice->setPort(ID::A, slice_signal(slice->getPort(ID::A)));
- if (slice->hasParam(ID::A_WIDTH))
- slice->setParam(ID::A_WIDTH, GetSize(slice->getPort(ID::A)));
+ for (IdString paramname : splitparams) {
+ if (slice->hasParam(paramname)) {
+ Const val = slice->getParam(paramname);
+ val = val.extract(slice_lsb, slice_msb-slice_lsb+1);
+ slice->setParam(paramname, val);
+ }
+ }
- if (slice->hasPort(ID::B)) {
- slice->setPort(ID::B, slice_signal(slice->getPort(ID::B)));
- if (slice->hasParam(ID::B_WIDTH))
- slice->setParam(ID::B_WIDTH, GetSize(slice->getPort(ID::B)));
- }
+ slice->setParam(ID::WIDTH, GetSize(slice->getPort(ID::Q)));
- slice->setPort(ID::Y, slice_signal(slice->getPort(ID::Y)));
- if (slice->hasParam(ID::Y_WIDTH))
- slice->setParam(ID::Y_WIDTH, GetSize(slice->getPort(ID::Y)));
- if (slice->hasParam(ID::WIDTH))
- slice->setParam(ID::WIDTH, GetSize(slice->getPort(ID::Y)));
+ log(" slice %d: %s => %s\n", i, log_id(slice_name), log_signal(slice->getPort(ID::Q)));
+ }
- log(" slice %d: %s => %s\n", i, log_id(slice_name), log_signal(slice->getPort(ID::Y)));
+ module->remove(cell);
+ return GetSize(slices)-1;
}
- module->remove(cell);
- return GetSize(slices)-1;
+ return 0;
}
};
@@ -179,14 +241,20 @@ struct SplitcellsPass : public Pass {
for (auto module : design->selected_modules())
{
- SplitcellsWorker worker(module);
int count_split_pre = 0;
int count_split_post = 0;
- for (auto cell : module->selected_cells()) {
- int n = worker.split(cell, format);
- count_split_pre += (n != 0);
- count_split_post += n;
+ while (1) {
+ SplitcellsWorker worker(module);
+ bool did_something = false;
+ for (auto cell : module->selected_cells()) {
+ int n = worker.split(cell, format);
+ did_something |= (n != 0);
+ count_split_pre += (n != 0);
+ count_split_post += n;
+ }
+ if (!did_something)
+ break;
}
if (count_split_pre)
diff --git a/techlibs/gowin/cells_sim.v b/techlibs/gowin/cells_sim.v
index 736aa0707..ab8207ef1 100644
--- a/techlibs/gowin/cells_sim.v
+++ b/techlibs/gowin/cells_sim.v
@@ -1553,6 +1553,53 @@ parameter DEVICE = "GW1N-1"; // "GW1N-1", "GW1N-4", "GW1N-9", "GW1NR-4",
endmodule
(* blackbox *)
+module PLLVR (CLKOUT, CLKOUTP, CLKOUTD, CLKOUTD3, LOCK, CLKIN, CLKFB, FBDSEL, IDSEL, ODSEL, DUTYDA, PSDA, FDLY, RESET, RESET_P, VREN);
+input CLKIN;
+input CLKFB;
+input RESET;
+input RESET_P;
+input [5:0] FBDSEL;
+input [5:0] IDSEL;
+input [5:0] ODSEL;
+input [3:0] PSDA,FDLY;
+input [3:0] DUTYDA;
+input VREN;
+
+output CLKOUT;
+output LOCK;
+output CLKOUTP;
+output CLKOUTD;
+output CLKOUTD3;
+
+parameter FCLKIN = "100.0"; // frequency of CLKIN
+parameter DYN_IDIV_SEL= "false"; // true:IDSEL, false:IDIV_SEL
+parameter IDIV_SEL = 0; // 0:1, 1:2 ... 63:64
+parameter DYN_FBDIV_SEL= "false"; // true:FBDSEL, false:FBDIV_SEL
+parameter FBDIV_SEL = 0; // 0:1, 1:2 ... 63:64
+parameter DYN_ODIV_SEL= "false"; // true:ODSEL, false:ODIV_SEL
+parameter ODIV_SEL = 8; // 2/4/8/16/32/48/64/80/96/112/128
+
+parameter PSDA_SEL= "0000";
+parameter DYN_DA_EN = "false"; // true:PSDA or DUTYDA or FDA, false: DA_SEL
+parameter DUTYDA_SEL= "1000";
+
+parameter CLKOUT_FT_DIR = 1'b1; // CLKOUT fine tuning direction. 1'b1 only
+parameter CLKOUTP_FT_DIR = 1'b1; // 1'b1 only
+parameter CLKOUT_DLY_STEP = 0; // 0, 1, 2, 4
+parameter CLKOUTP_DLY_STEP = 0; // 0, 1, 2
+
+parameter CLKFB_SEL = "internal"; // "internal", "external"
+parameter CLKOUT_BYPASS = "false"; // "true", "false"
+parameter CLKOUTP_BYPASS = "false"; // "true", "false"
+parameter CLKOUTD_BYPASS = "false"; // "true", "false"
+parameter DYN_SDIV_SEL = 2; // 2~128, only even numbers
+parameter CLKOUTD_SRC = "CLKOUT"; // CLKOUT, CLKOUTP
+parameter CLKOUTD3_SRC = "CLKOUT"; // CLKOUT, CLKOUTP
+parameter DEVICE = "GW1NS-4"; // "GW1NS-4", "GW1NS-4C", "GW1NSR-4", "GW1NSR-4C", "GW1NSER-4C"
+
+endmodule
+
+(* blackbox *)
module OSC(OSCOUT);
output OSCOUT;