Closed mkurc-ant closed 4 years ago
Any reason not to just merge with upstream master, versus the cherry pick?
Unclear. I will check whether the upstream Yosys works with Symbiflow. If it does then we can merge with upstream.
So unfortunately the upstream Yosys does not map carry of $alu
to CARRY4
but rather to a chain of CARRY0
+ 3x CARRY
which we don't support in VPR.
So unfortunately the upstream Yosys does not map carry of
$alu
toCARRY4
but rather to a chain ofCARRY0
+ 3xCARRY
which we don't support in VPR.
I meant merge master+wip with upstream master, which addresses your concern.
Current delta between upstream/master
and master+wip
after merging is the following;
diff --git a/Makefile b/Makefile
index 8e01ac13..25b95ff1 100644
--- a/Makefile
+++ b/Makefile
@@ -691,6 +691,7 @@ ABCOPT=""
endif
test: $(TARGETS) $(EXTRA_TARGETS)
+ +cd tests/round-trip && bash run-test.sh
+cd tests/simple && bash run-test.sh $(SEEDOPT)
+cd tests/simple_abc9 && bash run-test.sh $(SEEDOPT)
+cd tests/hana && bash run-test.sh $(SEEDOPT)
diff --git a/backends/ilang/ilang_backend.cc b/backends/ilang/ilang_backend.cc
index e0678622..9e1d1428 100644
--- a/backends/ilang/ilang_backend.cc
+++ b/backends/ilang/ilang_backend.cc
@@ -290,8 +290,19 @@ void ILANG_BACKEND::dump_module(std::ostream &f, std::string indent, RTLIL::Modu
if (!module->avail_parameters.empty()) {
if (only_selected)
f << stringf("\n");
- for (auto &p : module->avail_parameters)
+ for (auto &p : module->avail_parameters) {
+
+ if (module->parameter_attributes.count(p)) {
+ f << stringf("\n");
+ for (auto& attr : module->parameter_attributes.at(p)) {
+ f << stringf("%s" "attribute %s ", (indent + " ").c_str(), attr.first.c_str());
+ dump_const(f, attr.second);
+ f << stringf("\n");
+ }
+ }
+
f << stringf("%s" " parameter %s\n", indent.c_str(), p.c_str());
+ }
}
}
diff --git a/backends/json/json.cc b/backends/json/json.cc
index 107009ee..a60e0be1 100644
--- a/backends/json/json.cc
+++ b/backends/json/json.cc
@@ -116,7 +116,7 @@ struct JsonWriter
void write_parameters(const dict<IdString, Const> ¶meters, bool for_module=false)
{
bool first = true;
- for (auto ¶m : parameters) {
+ for (auto &attr : attributes) {
f << stringf("%s\n", first ? "" : ",");
f << stringf(" %s%s: ", for_module ? "" : " ", get_name(param.first).c_str());
write_parameter_value(param.second);
@@ -137,7 +137,11 @@ struct JsonWriter
f << stringf(" %s: {\n", get_name(module->name).c_str());
f << stringf(" \"attributes\": {");
- write_parameters(module->attributes, /*for_module=*/true);
+ write_attributes(module->attributes, /*for_module=*/true);
+ f << stringf("\n },\n");
+
+ f << stringf(" \"parameters\": {");
+ write_module_parameters(module);
f << stringf("\n },\n");
f << stringf(" \"ports\": {");
@@ -176,10 +180,10 @@ struct JsonWriter
}
}
f << stringf(" \"parameters\": {");
- write_parameters(c->parameters);
+ write_attributes(c->parameters);
f << stringf("\n },\n");
f << stringf(" \"attributes\": {");
- write_parameters(c->attributes);
+ write_attributes(c->attributes);
f << stringf("\n },\n");
if (c->known()) {
f << stringf(" \"port_directions\": {");
@@ -221,7 +225,7 @@ struct JsonWriter
if (w->upto)
f << stringf(" \"upto\": 1,\n");
f << stringf(" \"attributes\": {");
- write_parameters(w->attributes);
+ write_attributes(w->attributes);
f << stringf("\n }\n");
f << stringf(" }");
first = false;
diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc
index 7b1db477..ea225c3c 100644
--- a/backends/verilog/verilog_backend.cc
+++ b/backends/verilog/verilog_backend.cc
@@ -1629,6 +1629,36 @@ void dump_process(std::ostream &f, std::string indent, RTLIL::Process *proc, boo
}
}
+void dump_parameters(std::ostream &f, std::string indent, RTLIL::Module *module)
+{
+ for (auto& param : module->avail_parameters) {
+ std::string paramName;
+
+ RTLIL::ParameterInfo& info = module->parameter_information.at(param);
+
+ if (module->parameter_attributes.count(param)) {
+ dump_attributes(f, indent, module->parameter_attributes.at(param), '\n');
+ }
+
+ // Prefix the parameter name if needed
+ if (param.str().find("$") == 0) {
+ paramName = std::string("\\") + std::string(param.c_str());
+ }
+ else {
+ paramName = std::string(param.c_str());
+ }
+
+ f << stringf("%s" "parameter %s = ", indent.c_str(), paramName.c_str());
+ if (info.isReal) {
+ f << stringf("%f", info.defaultValueReal);
+ }
+ else {
+ dump_const(f, info.defaultValue);
+ }
+ f << stringf(";\n");
+ }
+}
+
void dump_module(std::ostream &f, std::string indent, RTLIL::Module *module)
{
reg_wires.clear();
@@ -1704,6 +1734,8 @@ void dump_module(std::ostream &f, std::string indent, RTLIL::Module *module)
}
f << stringf(");\n");
+ dump_parameters(f, indent + " ", module);
+
for (auto it = module->wires_.begin(); it != module->wires_.end(); ++it)
dump_wire(f, indent + " ", it->second);
diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc
index a3a78e41..49add93b 100644
--- a/frontends/ast/ast.cc
+++ b/frontends/ast/ast.cc
@@ -1053,7 +1053,6 @@ static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast
if (child->type == AST_WIRE && (child->is_input || child->is_output)) {
new_children.push_back(child);
} else if (child->type == AST_PARAMETER) {
- child->delete_children();
child->children.push_back(AstNode::mkconst_int(0, false, 0));
new_children.push_back(child);
} else if (child->type == AST_CELL && child->children.size() > 0 && child->children[0]->type == AST_CELLTYPE &&
diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc
index 407a3447..68792b1c 100644
--- a/frontends/ast/genrtlil.cc
+++ b/frontends/ast/genrtlil.cc
@@ -892,27 +892,42 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
case AST_INTERFACEPORTTYPE:
break;
- // remember the parameter, needed for example in techmap
- case AST_PARAMETER:
- current_module->avail_parameters.insert(str);
- /* fall through */
- case AST_LOCALPARAM:
- if (flag_pwires)
- {
- if (GetSize(children) < 1 || children[0]->type != AST_CONSTANT)
- log_file_error(filename, linenum, "Parameter `%s' with non-constant value!\n", str.c_str());
+ // create an RTLIL::Parameter for an AST_PARAMETER node
+ case AST_PARAMETER: {
+ current_module->avail_parameters.insert(str);
- RTLIL::Const val = children[0]->bitsAsConst();
- RTLIL::Wire *wire = current_module->addWire(str, GetSize(val));
- current_module->connect(wire, val);
+ // Add parameter information
+ log_assert(children.size() >= 1);
- wire->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum);
- wire->attributes[type == AST_PARAMETER ? "\\parameter" : "\\localparam"] = 1;
+ AstNode* child = children[0];
+ log_assert(child->type == AST_CONSTANT || child->type == AST_REALVALUE);
- for (auto &attr : attributes) {
- if (attr.second->type != AST_CONSTANT)
- log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str());
- wire->attributes[attr.first] = attr.second->asAttrConst();
+ RTLIL::ParameterInfo info;
+
+ if (child->type == AST_CONSTANT) {
+ info.defaultValue = child->asAttrConst();
+ }
+ else {
+ info.defaultValueReal = child->realvalue;
+ info.isReal = true;
+ }
+
+#ifdef WITH_PYTHON
+ info.name = str;
+#endif
+ current_module->parameter_information.insert(std::pair<RTLIL::IdString, RTLIL::ParameterInfo>(str, info));
+
+ // Add parameter attributes (if any)
+ if (!attributes.empty()) {
+ dict<RTLIL::IdString,RTLIL::Const> param_attrs;
+
+ for (auto &attr : attributes) {
+ if (attr.second->type != AST_CONSTANT)
+ log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str());
+ param_attrs[attr.first] = attr.second->asAttrConst();
+ }
+
+ current_module->parameter_attributes[str] = param_attrs;
}
}
break;
diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc
index 52fcf3ee..fa62ce32 100644
--- a/frontends/ast/simplify.cc
+++ b/frontends/ast/simplify.cc
@@ -2409,7 +2409,7 @@ skip_dynamic_range_lvalue_expansion:;
wire->is_input = false;
wire->is_output = false;
wire->is_reg = true;
- wire->attributes["\\nosync"] = AstNode::mkconst_int(1, false);
+ wire->attributes["\\nosync"] = AstNode::mkconst_int(1, false);
wire_cache[child->str] = wire;
current_ast_mod->children.push_back(wire);
@@ -2457,9 +2457,9 @@ skip_dynamic_range_lvalue_expansion:;
log_assert(it != current_block->children.end());
if (*it == current_block_child) {
current_block->children.insert(it, new_stmts.begin(), new_stmts.end());
- break;
+ break;
+ }
}
- }
replace_fcall_with_id:
if (type == AST_FCALL) {
diff --git a/frontends/ilang/ilang_parser.y b/frontends/ilang/ilang_parser.y
index b4b9693d..e33d30a4 100644
--- a/frontends/ilang/ilang_parser.y
+++ b/frontends/ilang/ilang_parser.y
@@ -148,6 +148,22 @@ module_stmt:
param_stmt:
TOK_PARAMETER TOK_ID EOL {
current_module->avail_parameters.insert($2);
+
+ // Assume that a parameter has default value of 0
+ RTLIL::ParameterInfo info;
+ info.defaultValue = 0;
+#ifdef WITH_PYTHON
+ info.name = $2;
+#endif
+
+ current_module->parameter_information.insert(std::pair<RTLIL::IdString,RTLIL::ParameterInfo>($2, info));
+
+ // Append attributes
+ if (!attrbuf.empty()) {
+ current_module->parameter_attributes[$2] = attrbuf;
+ attrbuf.clear();
+ }
+
free($2);
};
diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc
index 1d380135..cfc5a929 100644
--- a/kernel/rtlil.cc
+++ b/kernel/rtlil.cc
@@ -1446,6 +1446,17 @@ void RTLIL::Module::cloneInto(RTLIL::Module *new_mod) const
new_mod->avail_parameters = avail_parameters;
+ for (auto &info : parameter_information)
+ new_mod->parameter_information.insert(info);
+
+ for (auto &attrs : parameter_attributes)
+ {
+ dict<RTLIL::IdString,RTLIL::Const> attrs_copy;
+ for (auto &attr : attrs.second)
+ attrs_copy[attr.first] = attr.second;
+ new_mod->parameter_attributes[attrs.first] = attrs_copy;
+ }
+
for (auto &conn : connections_)
new_mod->connect(conn);
@@ -2352,6 +2363,32 @@ RTLIL::SigSpec RTLIL::Module::Initstate(RTLIL::IdString name, const std::string
return sig;
}
+RTLIL::ParameterInfo::ParameterInfo()
+{
+ static unsigned int hashidx_count = 123456789;
+ hashidx_count = mkhash_xorshift(hashidx_count);
+ hashidx_ = hashidx_count;
+
+#ifdef WITH_PYTHON
+ RTLIL::ParameterInfo::get_all_parameterinfos()->insert(std::pair<unsigned int, RTLIL::ParameterInfo*>(hashidx_, this));
+#endif
+}
+
+RTLIL::ParameterInfo::~ParameterInfo()
+{
+#ifdef WITH_PYTHON
+ RTLIL::ParameterInfo::get_all_parameterinfos()->erase(hashidx_);
+#endif
+}
+
+#ifdef WITH_PYTHON
+static std::map<unsigned int, RTLIL::ParameterInfo*> all_parameter_infos;
+std::map<unsigned int, RTLIL::ParameterInfo*> *RTLIL::ParameterInfo::get_all_parameterinfos(void)
+{
+ return &all_parameter_infos;
+}
+#endif
+
RTLIL::Wire::Wire()
{
static unsigned int hashidx_count = 123456789;
diff --git a/kernel/rtlil.h b/kernel/rtlil.h
index c08653b6..8a132d42 100644
--- a/kernel/rtlil.h
+++ b/kernel/rtlil.h
@@ -59,6 +59,7 @@ namespace RTLIL
struct Monitor;
struct Design;
struct Module;
+ struct ParameterInfo;
struct Wire;
struct Memory;
struct Cell;
@@ -1048,6 +1049,7 @@ public:
RTLIL::Design *design;
pool<RTLIL::Monitor*> monitors;
+ int refcount_parameters_;
int refcount_wires_;
int refcount_cells_;
@@ -1057,6 +1059,8 @@ public:
RTLIL::IdString name;
pool<RTLIL::IdString> avail_parameters;
+ dict<RTLIL::IdString, RTLIL::ParameterInfo> parameter_information;
+ dict<RTLIL::IdString, dict<RTLIL::IdString,RTLIL::Const>> parameter_attributes;
dict<RTLIL::IdString, RTLIL::Memory*> memories;
dict<RTLIL::IdString, RTLIL::Process*> processes;
@@ -1298,6 +1302,27 @@ public:
#endif
};
+struct RTLIL::ParameterInfo
+{
+ unsigned int hashidx_;
+ unsigned int hash() const { return hashidx_; }
+
+ ParameterInfo ();
+ ~ParameterInfo ();
+
+#ifdef WITH_PYTHON
+ RTLIL::IdString name;
+#endif
+ RTLIL::Const defaultValue = 0;
+
+ double defaultValueReal = 0.0;
+ bool isReal = false;
+
+#ifdef WITH_PYTHON
+ static std::map<unsigned int, RTLIL::ParameterInfo*> *get_all_parameterinfos(void);
+#endif
+};
+
struct RTLIL::Wire : public RTLIL::AttrObject
{
unsigned int hashidx_;
diff --git a/misc/py_wrap_generator.py b/misc/py_wrap_generator.py
index 2bf36447..cb90a940 100644
--- a/misc/py_wrap_generator.py
+++ b/misc/py_wrap_generator.py
@@ -947,7 +947,8 @@ sources = [
WClass("Wire", link_types.global_list, Attribute(WType("unsigned int"), "hashidx_"), "name.c_str()", "hash()"),
WClass("Memory", link_types.global_list, Attribute(WType("unsigned int"), "hashidx_"), "name.c_str()", "hash()"),
WClass("Module", link_types.global_list, Attribute(WType("unsigned int"), "hashidx_"), "name.c_str()", "hash()"),
- WClass("Design", link_types.global_list, Attribute(WType("unsigned int"), "hashidx_"), "hashidx_", "hash()")
+ WClass("Design", link_types.global_list, Attribute(WType("unsigned int"), "hashidx_"), "hashidx_", "hash()"),
+ WClass("ParameterInfo", link_types.global_list, Attribute(WType("unsigned int"), "hashidx_"), "name.c_str()", "hash()"),
]
),
#Source("kernel/satgen",[
diff --git a/techlibs/xilinx/arith_map.v b/techlibs/xilinx/arith_map.v
index 5c848d4e..4e64e6b0 100644
--- a/techlibs/xilinx/arith_map.v
+++ b/techlibs/xilinx/arith_map.v
@@ -52,7 +52,6 @@ module _80_xilinx_lcu (P, G, CI, CO);
CARRY4 carry4_1st_part
(
.CYINIT(CI),
- .CI (1'd0),
.DI (G [(Y_WIDTH - 1):i*4]),
.S (S [(Y_WIDTH - 1):i*4]),
.CO (CO[(Y_WIDTH - 1):i*4]),
@@ -61,7 +60,6 @@ module _80_xilinx_lcu (P, G, CI, CO);
end else begin
CARRY4 carry4_part
(
- .CYINIT(1'd0),
.CI (C [i*4 - 1]),
.DI (G [(Y_WIDTH - 1):i*4]),
.S (S [(Y_WIDTH - 1):i*4]),
@@ -77,7 +75,6 @@ module _80_xilinx_lcu (P, G, CI, CO);
CARRY4 carry4_1st_full
(
.CYINIT(CI),
- .CI (1'd0),
.DI (G [((i+1)*4 - 1):i*4]),
.S (S [((i+1)*4 - 1):i*4]),
.CO (CO[((i+1)*4 - 1):i*4]),
@@ -86,7 +83,6 @@ module _80_xilinx_lcu (P, G, CI, CO);
end else begin
CARRY4 carry4_full
(
- .CYINIT(1'd0),
.CI (C [i*4 - 1]),
.DI (G [((i+1)*4 - 1):i*4]),
.S (S [((i+1)*4 - 1):i*4]),
@@ -183,7 +179,6 @@ module _80_xilinx_alu (A, B, CI, BI, X, Y, CO);
CARRY4 carry4_1st_part
(
.CYINIT(CI),
- .CI (1'd0),
.DI (DI[(Y_WIDTH - 1):i*4]),
.S (S [(Y_WIDTH - 1):i*4]),
.O (Y [(Y_WIDTH - 1):i*4]),
@@ -193,7 +188,6 @@ module _80_xilinx_alu (A, B, CI, BI, X, Y, CO);
end else begin
CARRY4 carry4_part
(
- .CYINIT(1'd0),
.CI (C [i*4 - 1]),
.DI (DI[(Y_WIDTH - 1):i*4]),
.S (S [(Y_WIDTH - 1):i*4]),
@@ -210,7 +204,6 @@ module _80_xilinx_alu (A, B, CI, BI, X, Y, CO);
CARRY4 carry4_1st_full
(
.CYINIT(CI),
- .CI (1'd0),
.DI (DI[((i+1)*4 - 1):i*4]),
.S (S [((i+1)*4 - 1):i*4]),
.O (Y [((i+1)*4 - 1):i*4]),
@@ -220,7 +213,6 @@ module _80_xilinx_alu (A, B, CI, BI, X, Y, CO);
end else begin
CARRY4 carry4_full
(
- .CYINIT(1'd0),
.CI (C [i*4 - 1]),
.DI (DI[((i+1)*4 - 1):i*4]),
.S (S [((i+1)*4 - 1):i*4]),
@@ -235,100 +227,98 @@ module _80_xilinx_alu (A, B, CI, BI, X, Y, CO);
`elsif _EXPLICIT_CARRY
- wire [Y_WIDTH-1:0] S = AA ^ BB;
- wire [Y_WIDTH-1:0] DI = AA & BB;
+ // Turns out CO and O both use [ABCD]MUX, so provide a non-congested path
+ // to output the top of the carry chain is required.
+ //
+ // Registering the output of the CARRY block would solve this, but not
+ // all designs do that.
+ //
+ // To ensure that PAD_WIDTH > 0, add 1 to Y_WIDTH.
+ localparam Y_PAD_WIDTH = Y_WIDTH + 1;
+ localparam CARRY4_COUNT = (Y_PAD_WIDTH + 3) / 4;
+ localparam MAX_WIDTH = CARRY4_COUNT * 4;
+ localparam PAD_WIDTH = MAX_WIDTH - Y_WIDTH;
+
+ wire [Y_PAD_WIDTH-1:0] O;
+ wire [MAX_WIDTH-1:0] S = {{PAD_WIDTH{1'b0}}, AA ^ BB};
+ wire [MAX_WIDTH-1:0] DI = {{PAD_WIDTH{1'b0}}, AA & BB};
- wire CINIT;
- // Carry chain.
+ // Carry chain between CARRY4 blocks.
//
- // VPR requires that the carry chain never hit the fabric. The CO input
+ // VPR requires that the carry chain never hit the fabric. The CO input
// to this techmap is the carry outputs for synthesis, e.g. might hit the
// fabric.
//
// So we maintain two wire sets, CO_CHAIN is the carry that is for VPR,
// e.g. off fabric dedicated chain. CO is the carry outputs that are
// available to the fabric.
- wire [Y_WIDTH-1:0] CO_CHAIN;
- wire [Y_WIDTH-1:0] C = {CO_CHAIN, CINIT};
-
- // If carry chain is being initialized to a constant, techmap the constant
- // source. Otherwise techmap the fabric source.
- generate for (i = 0; i < 1; i = i + 1) begin:slice
- CARRY0 #(.CYINIT_FABRIC(1)) carry(
- .CI_INIT(CI),
- .DI(DI[0]),
- .S(S[0]),
- .CO_CHAIN(CO_CHAIN[0]),
- .CO_FABRIC(CO[0]),
- .O(Y[0])
- );
- end endgenerate
+ wire [CARRY4_COUNT-1:0] CO_CHAIN;
+ wire [MAX_WIDTH-1:0] CO_FABRIC;
- generate for (i = 1; i < Y_WIDTH-1; i = i + 1) begin:slice
- if(i % 4 == 0) begin
- CARRY0 carry (
- .CI(C[i]),
- .DI(DI[i]),
- .S(S[i]),
- .CO_CHAIN(CO_CHAIN[i]),
- .CO_FABRIC(CO[i]),
- .O(Y[i])
- );
- end
- else
- begin
- CARRY carry (
- .CI(C[i]),
- .DI(DI[i]),
- .S(S[i]),
- .CO_CHAIN(CO_CHAIN[i]),
- .CO_FABRIC(CO[i]),
- .O(Y[i])
- );
- end
- end endgenerate
+ assign Y[Y_WIDTH-1:0] = O[Y_WIDTH-1:0];
+ assign CO[Y_WIDTH-2:0] = CO_FABRIC[Y_WIDTH-2:0];
+
+ // Use a dedicated CO pin (e.g. no O pin) to avoid [ABCD]MUX congestion
+ // for top of carry.
+ assign CO[Y_WIDTH-1] = CO_FABRIC[Y_WIDTH];
+
+ genvar i;
+ generate for (i = 0; i < CARRY4_COUNT; i = i + 1) begin:slice
+
+ // Partially occupied CARRY4
+ if ((i+1)*4 > Y_PAD_WIDTH) begin
+
+ // First one
+ if (i == 0) begin
+ CARRY4_COUT carry4_1st_part
+ (
+ .CYINIT(CI),
+ .DI (DI[(Y_PAD_WIDTH - 1):i*4]),
+ .S (S [(Y_PAD_WIDTH - 1):i*4]),
+ .O (O [(Y_PAD_WIDTH - 1):i*4]),
+ .CO (CO_FABRIC[(Y_PAD_WIDTH - 1):i*4]),
+ );
+ // Another one
+ end else begin
+ CARRY4_COUT carry4_part
+ (
+ .CI (CO_CHAIN [i-1]),
+ .DI (DI[(Y_PAD_WIDTH - 1):i*4]),
+ .S (S [(Y_PAD_WIDTH - 1):i*4]),
+ .O (O [(Y_PAD_WIDTH - 1):i*4]),
+ .CO (CO_FABRIC[(Y_PAD_WIDTH - 1):i*4])
+ );
+ end
+
+ // Fully occupied CARRY4
+ end else begin
+
+ // First one
+ if (i == 0) begin
+ CARRY4_COUT carry4_1st_full
+ (
+ .CYINIT(CI),
+ .DI (DI[((i+1)*4 - 1):i*4]),
+ .S (S [((i+1)*4 - 1):i*4]),
+ .O (O [((i+1)*4 - 1):i*4]),
+ .CO (CO_FABRIC[((i+1)*4 - 1):i*4]),
+ .COUT(CO_CHAIN[i])
+ );
+ // Another one
+ end else begin
+ CARRY4_COUT carry4_full
+ (
+ .CI (CO_CHAIN[i-1]),
+ .DI (DI[((i+1)*4 - 1):i*4]),
+ .S (S [((i+1)*4 - 1):i*4]),
+ .O (O [((i+1)*4 - 1):i*4]),
+ .CO (CO_FABRIC[((i+1)*4 - 1):i*4]),
+ .COUT(CO_CHAIN[i])
+ );
+ end
- generate for (i = Y_WIDTH-1; i < Y_WIDTH; i = i + 1) begin:slice
- if(i % 4 == 0) begin
- CARRY0 top_of_carry (
- .CI(C[i]),
- .DI(DI[i]),
- .S(S[i]),
- .CO_CHAIN(CO_CHAIN[i]),
- .O(Y[i])
- );
- end
- else
- begin
- CARRY top_of_carry (
- .CI(C[i]),
- .DI(DI[i]),
- .S(S[i]),
- .CO_CHAIN(CO_CHAIN[i]),
- .O(Y[i])
- );
- end
- // Turns out CO_FABRIC and O both use [ABCD]MUX, so provide
- // a non-congested path to output the top of the carry chain.
- // Registering the output of the CARRY block would solve this, but not
- // all designs do that.
- if((i+1) % 4 == 0) begin
- CARRY0 carry_output (
- .CI(CO_CHAIN[i]),
- .DI(0),
- .S(0),
- .O(CO[i])
- );
- end
- else
- begin
- CARRY carry_output (
- .CI(CO_CHAIN[i]),
- .DI(0),
- .S(0),
- .O(CO[i])
- );
end
+
end endgenerate
`else
diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v
index e12b77c0..fc0f5edf 100644
--- a/techlibs/xilinx/cells_sim.v
+++ b/techlibs/xilinx/cells_sim.v
@@ -215,23 +215,14 @@ endmodule
`ifdef _EXPLICIT_CARRY
-module CARRY0(output CO_CHAIN, CO_FABRIC, O, input CI, CI_INIT, DI, S);
- parameter CYINIT_FABRIC = 0;
- wire CI_COMBINE;
- if(CYINIT_FABRIC) begin
- assign CI_COMBINE = CI_INIT;
- end else begin
- assign CI_COMBINE = CI;
- end
- assign CO_CHAIN = S ? CI_COMBINE : DI;
- assign CO_FABRIC = S ? CI_COMBINE : DI;
- assign O = S ^ CI_COMBINE;
-endmodule
-
-module CARRY(output CO_CHAIN, CO_FABRIC, O, input CI, DI, S);
- assign CO_CHAIN = S ? CI : DI;
- assign CO_FABRIC = S ? CI : DI;
- assign O = S ^ CI;
+module CARRY4_COUT(output [3:0] CO, O, output COUT, input CI, CYINIT, input [3:0] DI, S);
+ assign O = S ^ {CO[2:0], CI | CYINIT};
+ assign CO[0] = S[0] ? CI | CYINIT : DI[0];
+ assign CO[1] = S[1] ? CO[0] : DI[1];
+ assign CO[2] = S[2] ? CO[1] : DI[2];
+ wire CO_TOP = S[3] ? CO[2] : DI[3];
+ assign CO[3] = CO_TOP;
+ assign COUT = CO_TOP;
endmodule
`endif
diff --git a/techlibs/xilinx/xc7_brams.txt b/techlibs/xilinx/xc7_brams.txt
index f1161114..138540b2 100644
--- a/techlibs/xilinx/xc7_brams.txt
+++ b/techlibs/xilinx/xc7_brams.txt
@@ -72,13 +72,15 @@ bram $__XILINX_RAMB18_TDP
clkpol 2 3
endbram
-match $__XILINX_RAMB36_SDP
- min bits 4096
- min efficiency 5
- shuffle_enable B
- make_transp
- or_next_if_better
-endmatch
+# Disable RAMB36 synthesis until https://github.com/SymbiFlow/symbiflow-arch-defs/issues/438
+# is solved.
+#match $__XILINX_RAMB36_SDP
+# min bits 4096
+# min efficiency 5
+# shuffle_enable B
+# make_transp
+# or_next_if_better
+#endmatch
match $__XILINX_RAMB18_SDP
min bits 4096
@@ -88,13 +90,13 @@ match $__XILINX_RAMB18_SDP
or_next_if_better
endmatch
-match $__XILINX_RAMB36_TDP
- min bits 4096
- min efficiency 5
- shuffle_enable B
- make_transp
- or_next_if_better
-endmatch
+#match $__XILINX_RAMB36_TDP
+# min bits 4096
+# min efficiency 5
+# shuffle_enable B
+# make_transp
+# or_next_if_better
+#endmatch
match $__XILINX_RAMB18_TDP
min bits 4096
diff --git a/tests/round-trip/parameter_types.v b/tests/round-trip/parameter_types.v
new file mode 100644
index 00000000..db6a198b
--- /dev/null
+++ b/tests/round-trip/parameter_types.v
@@ -0,0 +1,11 @@
+module box (I, O);
+ input wire I;
+ output wire O;
+
+ parameter PARAM_STRING = "A string.";
+ parameter PARAM_INTEGER = 10;
+ parameter PARAM_REAL = 3.14;
+
+ assign O = I;
+
+endmodule
diff --git a/tests/round-trip/parameters.v b/tests/round-trip/parameters.v
new file mode 100644
index 00000000..76699c6c
--- /dev/null
+++ b/tests/round-trip/parameters.v
@@ -0,0 +1,34 @@
+module child_no_params (I, O);
+ input wire I;
+ output wire O;
+
+ assign O = I[0];
+endmodule
+
+module child (I, O);
+ (* CHILD_ATTR = 1 *)
+ parameter CHILD_WIDTH = 1;
+ (* CHILD_ATTR2 = 0 *)
+ localparam CHILD_LOCALPARAM = CHILD_WIDTH;
+
+ input wire [CHILD_LOCALPARAM-1:0] I;
+ output wire O;
+
+ assign O = I[0];
+endmodule
+
+module parent (I, O1, O2);
+ (* PARENT_ATTR = "parent_attr" *)
+ parameter PARENT_WIDTH = 1;
+ parameter PARENT_MODE = "MODE_NAME";
+ parameter [7:0] PARENT_STUFF = 0;
+
+ input wire [PARENT_WIDTH-1:0] I;
+ output wire O1;
+ output wire O2;
+
+ child #(.CHILD_WIDTH(PARENT_WIDTH)) child_inst1 (I, O1);
+
+ child child_inst2 (I[0], O2);
+
+endmodule
diff --git a/tests/round-trip/run-test.sh b/tests/round-trip/run-test.sh
new file mode 100644
index 00000000..4a1f54fc
--- /dev/null
+++ b/tests/round-trip/run-test.sh
@@ -0,0 +1,42 @@
+#!/bin/bash
+
+# Single round-trip test
+run_single_test () {
+ set -e
+
+ # Frontent options
+ if [ "$LANG" == "verilog" ]; then
+ FRONTEND_OPTS="-nolatches -nomem2reg -nopp -noopt -noautowire -icells"
+ else
+ FRONTEND_OPTS=""
+ fi
+
+ # Initial run
+ ../../../yosys -ql yosys.log -p "read_verilog "../${SOURCE}"; write_"${LANG}" round_trip.1"
+ # Round-trip run
+ ../../../yosys -ql yosys.log -p "read_"${LANG}" ""${FRONTEND_OPTS}"" round_trip.1; write_"${LANG}" round_trip.2"
+
+ # Sort output lines
+ sort round_trip.1 > round_trip.1.sorted
+ sort round_trip.2 > round_trip.2.sorted
+
+ # Check
+ set +e
+ diff -q -B -y round_trip.2.sorted round_trip.1.sorted
+ if [ $? -ne 0 ]; then
+ echo "Test failed! Output after round-trip differs!"
+ exit -1
+ fi
+}
+
+# Run tests
+for SOURCE in *.v; do
+ for LANG in verilog ilang; do
+ WORKDIR=work_$(basename ${SOURCE%.*})_${LANG}
+ mkdir -p ${WORKDIR}
+ cd ${WORKDIR}
+ run_single_test
+ cd ..
+ done
+done
+
With the new master+wip, this has been merged in already
This is a cherry picked commit from YosysHQ which adds the simulation model of SRLC16E (with Q15 output) primitive.
https://github.com/YosysHQ/yosys/issues/1331