summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClifford Wolf <clifford@clifford.at>2013-11-24 17:17:21 +0100
committerClifford Wolf <clifford@clifford.at>2013-11-24 17:17:21 +0100
commit609caa23b5e12547c043dc4a1827d1a531af1992 (patch)
tree297e7d5b77b28eebccc3bd8e7af318f174165744
parent1e6836933d8b74d391f816ccdcf71c972f8b1db1 (diff)
Implemented correct handling of signed module parameters
-rw-r--r--frontends/ast/ast.cc4
-rw-r--r--frontends/ast/ast.h2
-rw-r--r--frontends/ast/genrtlil.cc4
-rw-r--r--kernel/rtlil.cc2
-rw-r--r--kernel/rtlil.h3
-rw-r--r--passes/hierarchy/hierarchy.cc2
-rw-r--r--passes/techmap/techmap.cc2
-rw-r--r--tests/simple/hierarchy.v8
8 files changed, 19 insertions, 8 deletions
diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc
index 29093b83..6423cae2 100644
--- a/frontends/ast/ast.cc
+++ b/frontends/ast/ast.cc
@@ -792,7 +792,7 @@ AstModule::~AstModule()
}
// create a new parametric module (when needed) and return the name of the generated module
-RTLIL::IdString AstModule::derive(RTLIL::Design *design, std::map<RTLIL::IdString, RTLIL::Const> parameters)
+RTLIL::IdString AstModule::derive(RTLIL::Design *design, std::map<RTLIL::IdString, RTLIL::Const> parameters, std::set<RTLIL::IdString> signed_parameters)
{
log_header("Executing AST frontend in derive mode using pre-parsed AST for module `%s'.\n", name.c_str());
@@ -826,7 +826,7 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, std::map<RTLIL::IdStrin
rewrite_parameter:
para_info += stringf("%s=%s", child->str.c_str(), log_signal(RTLIL::SigSpec(parameters[para_id])));
delete child->children.at(0);
- child->children[0] = AstNode::mkconst_bits(parameters[para_id].bits, child->is_signed);
+ child->children[0] = AstNode::mkconst_bits(parameters[para_id].bits, signed_parameters.count(para_id) > 0);
hash_data.insert(hash_data.end(), child->str.begin(), child->str.end());
hash_data.push_back(0);
hash_data.insert(hash_data.end(), parameters[para_id].bits.begin(), parameters[para_id].bits.end());
diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h
index de32a2bb..f9f47f6a 100644
--- a/frontends/ast/ast.h
+++ b/frontends/ast/ast.h
@@ -227,7 +227,7 @@ namespace AST
AstNode *ast;
bool nolatches, nomem2reg, mem2reg, lib, noopt;
virtual ~AstModule();
- virtual RTLIL::IdString derive(RTLIL::Design *design, std::map<RTLIL::IdString, RTLIL::Const> parameters);
+ virtual RTLIL::IdString derive(RTLIL::Design *design, std::map<RTLIL::IdString, RTLIL::Const> parameters, std::set<RTLIL::IdString> signed_parameters);
virtual void update_auto_wires(std::map<RTLIL::IdString, int> auto_sizes);
virtual RTLIL::Module *clone() const;
};
diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc
index e634a27a..177c1ec5 100644
--- a/frontends/ast/genrtlil.cc
+++ b/frontends/ast/genrtlil.cc
@@ -1309,9 +1309,13 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
if (child->str.size() == 0) {
char buf[100];
snprintf(buf, 100, "$%d", ++para_counter);
+ if (child->children[0]->is_signed)
+ cell->signed_parameters.insert(buf);
cell->parameters[buf].str = child->children[0]->str;
cell->parameters[buf].bits = child->children[0]->bits;
} else {
+ if (child->children[0]->is_signed)
+ cell->signed_parameters.insert(child->str);
cell->parameters[child->str].str = child->children[0]->str;
cell->parameters[child->str].bits = child->children[0]->bits;
}
diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc
index bd73fe53..afd7ca2f 100644
--- a/kernel/rtlil.cc
+++ b/kernel/rtlil.cc
@@ -260,7 +260,7 @@ RTLIL::Module::~Module()
delete it->second;
}
-RTLIL::IdString RTLIL::Module::derive(RTLIL::Design*, std::map<RTLIL::IdString, RTLIL::Const>)
+RTLIL::IdString RTLIL::Module::derive(RTLIL::Design*, std::map<RTLIL::IdString, RTLIL::Const>, std::set<RTLIL::IdString>)
{
log_error("Module `%s' is used with parameters but is not parametric!\n", id2cstr(name));
}
diff --git a/kernel/rtlil.h b/kernel/rtlil.h
index c7f9cf12..a4c3008b 100644
--- a/kernel/rtlil.h
+++ b/kernel/rtlil.h
@@ -264,7 +264,7 @@ struct RTLIL::Module {
std::vector<RTLIL::SigSig> connections;
RTLIL_ATTRIBUTE_MEMBERS
virtual ~Module();
- virtual RTLIL::IdString derive(RTLIL::Design *design, std::map<RTLIL::IdString, RTLIL::Const> parameters);
+ virtual RTLIL::IdString derive(RTLIL::Design *design, std::map<RTLIL::IdString, RTLIL::Const> parameters, std::set<RTLIL::IdString> signed_parameters);
virtual void update_auto_wires(std::map<RTLIL::IdString, int> auto_sizes);
virtual size_t count_id(RTLIL::IdString id);
virtual void check();
@@ -300,6 +300,7 @@ struct RTLIL::Cell {
RTLIL::IdString type;
std::map<RTLIL::IdString, RTLIL::SigSpec> connections;
std::map<RTLIL::IdString, RTLIL::Const> parameters;
+ std::set<RTLIL::IdString> signed_parameters;
RTLIL_ATTRIBUTE_MEMBERS
void optimize();
diff --git a/passes/hierarchy/hierarchy.cc b/passes/hierarchy/hierarchy.cc
index d9b52c6d..291df184 100644
--- a/passes/hierarchy/hierarchy.cc
+++ b/passes/hierarchy/hierarchy.cc
@@ -150,7 +150,7 @@ static bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool fla
if (design->modules.at(cell->type)->get_bool_attribute("\\blackbox"))
continue;
RTLIL::Module *mod = design->modules[cell->type];
- cell->type = mod->derive(design, cell->parameters);
+ cell->type = mod->derive(design, cell->parameters, cell->signed_parameters);
cell->parameters.clear();
did_something = true;
}
diff --git a/passes/techmap/techmap.cc b/passes/techmap/techmap.cc
index 4f9d9c4e..c3af697b 100644
--- a/passes/techmap/techmap.cc
+++ b/passes/techmap/techmap.cc
@@ -239,7 +239,7 @@ static bool techmap_module(RTLIL::Design *design, RTLIL::Module *module, RTLIL::
tpl = techmap_cache[key];
} else {
if (cell->parameters.size() != 0) {
- derived_name = tpl->derive(map, parameters);
+ derived_name = tpl->derive(map, parameters, cell->signed_parameters);
tpl = map->modules[derived_name];
log_continue = true;
}
diff --git a/tests/simple/hierarchy.v b/tests/simple/hierarchy.v
index 97612c74..17888009 100644
--- a/tests/simple/hierarchy.v
+++ b/tests/simple/hierarchy.v
@@ -4,14 +4,20 @@ module top(a, b, y1, y2, y3, y4);
input [3:0] a;
input signed [3:0] b;
output [7:0] y1, y2, y3, y4;
+
+// this version triggers a bug in icarus verilog
+// submod #(-3'sd1, 3'b111 + 3'b001) foo (a, b, y1, y2, y3, y4);
+
+// this version is handled correctly by icarus verilog
submod #(-3'sd1, -3'sd1) foo (a, b, y1, y2, y3, y4);
+
endmodule
(* gentb_skip *)
module submod(a, b, y1, y2, y3, y4);
parameter c = 0;
parameter [7:0] d = 0;
-input [7:0] a, b;
+input [3:0] a, b;
output [7:0] y1, y2, y3, y4;
assign y1 = a;
assign y2 = b;