summaryrefslogtreecommitdiff
path: root/frontends
diff options
context:
space:
mode:
authorClifford Wolf <clifford@clifford.at>2014-07-28 14:25:03 +0200
committerClifford Wolf <clifford@clifford.at>2014-07-28 14:25:03 +0200
commit27a872d1e7041be4894bc643a420587ff5894125 (patch)
tree430d0411eaa4c4f6893576e2179d2eee93726def /frontends
parent3c45277ee0f5822181c6058f679de632f834e7d2 (diff)
Added support for "upto" wires to Verilog front- and back-end
Diffstat (limited to 'frontends')
-rw-r--r--frontends/ast/ast.cc5
-rw-r--r--frontends/ast/ast.h2
-rw-r--r--frontends/ast/genrtlil.cc19
-rw-r--r--frontends/ast/simplify.cc4
4 files changed, 17 insertions, 13 deletions
diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc
index cec199b6..5b3214f5 100644
--- a/frontends/ast/ast.cc
+++ b/frontends/ast/ast.cc
@@ -181,6 +181,7 @@ AstNode::AstNode(AstNodeType type, AstNode *child1, AstNode *child2)
is_signed = false;
is_string = false;
range_valid = false;
+ range_swapped = false;
port_id = 0;
range_left = -1;
range_right = 0;
@@ -276,7 +277,7 @@ void AstNode::dumpAst(FILE *f, std::string indent)
if (port_id > 0)
fprintf(f, " port=%d", port_id);
if (range_valid || range_left != -1 || range_right != 0)
- fprintf(f, " range=[%d:%d]%s", range_left, range_right, range_valid ? "" : "!");
+ fprintf(f, " %srange=[%d:%d]%s", range_swapped ? "swapped_" : "", range_left, range_right, range_valid ? "" : "!");
if (integer != 0)
fprintf(f, " int=%u", (int)integer);
if (realvalue != 0)
@@ -620,6 +621,8 @@ bool AstNode::operator==(const AstNode &other) const
return false;
if (range_valid != other.range_valid)
return false;
+ if (range_swapped != other.range_swapped)
+ return false;
if (port_id != other.port_id)
return false;
if (range_left != other.range_left)
diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h
index 8253a205..6c15c03a 100644
--- a/frontends/ast/ast.h
+++ b/frontends/ast/ast.h
@@ -151,7 +151,7 @@ namespace AST
// node content - most of it is unused in most node types
std::string str;
std::vector<RTLIL::State> bits;
- bool is_input, is_output, is_reg, is_signed, is_string, range_valid;
+ bool is_input, is_output, is_reg, is_signed, is_string, range_valid, range_swapped;
int port_id, range_left, range_right;
uint32_t integer;
double realvalue;
diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc
index 8ee46eb8..5545fc16 100644
--- a/frontends/ast/genrtlil.cc
+++ b/frontends/ast/genrtlil.cc
@@ -786,13 +786,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
log_error("Signal `%s' with non-constant width at %s:%d!\n",
str.c_str(), filename.c_str(), linenum);
- bool wire_upto = false;
- if (range_left < range_right && (range_left != -1 || range_right != 0)) {
- int tmp = range_left;
- range_left = range_right;
- range_right = tmp;
- wire_upto = true;
- }
+ log_assert(range_left >= range_right || (range_left == -1 && range_right == 0));
RTLIL::Wire *wire = current_module->addWire(str, range_left - range_right + 1);
wire->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum);
@@ -800,7 +794,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
wire->port_id = port_id;
wire->port_input = is_input;
wire->port_output = is_output;
- wire->upto = wire_upto;
+ wire->upto = range_swapped;
for (auto &attr : attributes) {
if (attr.second->type != AST_CONSTANT)
@@ -918,17 +912,20 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
children[0]->children[1]->clone() : children[0]->children[0]->clone());
fake_ast->children[0]->delete_children();
RTLIL::SigSpec sig = binop2rtlil(fake_ast, "$shr", width,
- fake_ast->children[0]->genRTLIL(), fake_ast->children[1]->genRTLIL());
+ fake_ast->children[0]->genRTLIL(), !wire->upto ? fake_ast->children[1]->genRTLIL() :
+ current_module->Sub(NEW_ID, RTLIL::SigSpec(wire->width - width), fake_ast->children[1]->genRTLIL()));
delete left_at_zero_ast;
delete right_at_zero_ast;
delete fake_ast;
return sig;
} else {
- chunk.offset = children[0]->range_right - id2ast->range_right;
- chunk.width = children[0]->range_left - children[0]->range_right + 1;
if (children[0]->range_left > id2ast->range_left || id2ast->range_right > children[0]->range_right)
log_error("Range select out of bounds on signal `%s' at %s:%d!\n",
str.c_str(), filename.c_str(), linenum);
+ chunk.width = children[0]->range_left - children[0]->range_right + 1;
+ chunk.offset = children[0]->range_right - id2ast->range_right;
+ if (wire->upto)
+ chunk.offset = wire->width - (chunk.offset + chunk.width);
}
}
diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc
index 2a55adef..7aa6d24c 100644
--- a/frontends/ast/simplify.cc
+++ b/frontends/ast/simplify.cc
@@ -504,6 +504,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
if (type == AST_RANGE) {
bool old_range_valid = range_valid;
range_valid = false;
+ range_swapped = false;
range_left = -1;
range_right = 0;
log_assert(children.size() >= 1);
@@ -525,6 +526,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
int tmp = range_right;
range_right = range_left;
range_left = tmp;
+ range_swapped = true;
}
}
@@ -535,6 +537,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
if (!range_valid)
did_something = true;
range_valid = true;
+ range_swapped = children[0]->range_swapped;
range_left = children[0]->range_left;
range_right = children[0]->range_right;
}
@@ -542,6 +545,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
if (!range_valid)
did_something = true;
range_valid = true;
+ range_swapped = false;
range_left = 0;
range_right = 0;
}