aboutsummaryrefslogtreecommitdiffstats
path: root/frontends/ast
diff options
context:
space:
mode:
authorJeff Wang <jjj11x@gmail.com>2018-03-09 12:47:11 +0000
committerJeff Wang <jeffrey.wang@ll.mit.edu>2020-01-16 13:51:47 -0500
commit16ea4ea61abd8f000564b3bfe1c88246c1caf631 (patch)
treea7ccb4fc5f099428177df00a0a2258057146d610 /frontends/ast
parent2bda51ac34d6f542d1d6477eecede1d6527c10b3 (diff)
downloadyosys-16ea4ea61abd8f000564b3bfe1c88246c1caf631.tar.gz
yosys-16ea4ea61abd8f000564b3bfe1c88246c1caf631.tar.bz2
yosys-16ea4ea61abd8f000564b3bfe1c88246c1caf631.zip
partial rebase of PeterCrozier's enum work onto current master
I tried to keep only the enum-related changes, and minimize the diff. (The original commit also had a lot of work done to get typedefs working, but yosys has diverged quite a bit since the 2018-03-09 commit, with a new typedef implementation.) I did not include the import related changes either. Original commit: "Initial implementation of enum, typedef, import. Still a WIP." https://github.com/PeterCrozier/yosys/commit/881833aa738e7404987646ea8076284e911fce3f
Diffstat (limited to 'frontends/ast')
-rw-r--r--frontends/ast/ast.cc23
-rw-r--r--frontends/ast/ast.h7
-rw-r--r--frontends/ast/genrtlil.cc8
-rw-r--r--frontends/ast/simplify.cc95
4 files changed, 117 insertions, 16 deletions
diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc
index 5bbea0faf..135750837 100644
--- a/frontends/ast/ast.cc
+++ b/frontends/ast/ast.cc
@@ -88,6 +88,8 @@ std::string AST::type2str(AstNodeType type)
X(AST_LIVE)
X(AST_FAIR)
X(AST_COVER)
+ X(AST_ENUM)
+ X(AST_ENUM_ITEM)
X(AST_FCALL)
X(AST_TO_BITS)
X(AST_TO_SIGNED)
@@ -202,6 +204,7 @@ AstNode::AstNode(AstNodeType type, AstNode *child1, AstNode *child2, AstNode *ch
is_logic = false;
is_signed = false;
is_string = false;
+ is_enum = false;
is_wand = false;
is_wor = false;
is_unsized = false;
@@ -321,6 +324,9 @@ void AstNode::dumpAst(FILE *f, std::string indent) const
fprintf(f, " %d", v);
fprintf(f, " ]");
}
+ if (is_enum) {
+ fprintf(f, " type=enum");
+ }
fprintf(f, "\n");
for (auto &it : attributes) {
@@ -1174,7 +1180,15 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump
for (auto n : design->verilog_packages){
for (auto o : n->children) {
AstNode *cloned_node = o->clone();
- cloned_node->str = n->str + std::string("::") + cloned_node->str.substr(1);
+ log("cloned node %s\n", type2str(cloned_node->type).c_str());
+ if (cloned_node->type == AST_ENUM){
+ for (auto e : cloned_node->children){
+ log_assert(e->type == AST_ENUM_ITEM);
+ e->str = n->str + std::string("::") + e->str.substr(1);
+ }
+ } else {
+ cloned_node->str = n->str + std::string("::") + cloned_node->str.substr(1);
+ }
(*it)->children.push_back(cloned_node);
}
}
@@ -1203,10 +1217,13 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump
design->add(process_module(*it, defer));
}
- else if ((*it)->type == AST_PACKAGE)
+ else if ((*it)->type == AST_PACKAGE) {
design->verilog_packages.push_back((*it)->clone());
- else
+ }
+ else {
+ // must be global definition
design->verilog_globals.push_back((*it)->clone());
+ }
}
}
diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h
index 918d178c7..ffdcd9271 100644
--- a/frontends/ast/ast.h
+++ b/frontends/ast/ast.h
@@ -68,6 +68,8 @@ namespace AST
AST_LIVE,
AST_FAIR,
AST_COVER,
+ AST_ENUM,
+ AST_ENUM_ITEM,
AST_FCALL,
AST_TO_BITS,
@@ -181,6 +183,8 @@ namespace AST
int port_id, range_left, range_right;
uint32_t integer;
double realvalue;
+ // set for IDs typed to an enumeration, not used
+ bool is_enum;
// if this is a multirange memory then this vector contains offset and length of each dimension
std::vector<int> multirange_dimensions;
@@ -285,6 +289,9 @@ namespace AST
int isConst() const; // return '1' for AST_CONSTANT and '2' for AST_REALVALUE
double asReal(bool is_signed);
RTLIL::Const realAsConst(int width);
+
+ // helpers for enum
+ void allocateDefaultEnumValues();
};
// process an AST tree (ast must point to an AST_DESIGN node) and generate RTLIL code
diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc
index 94f5c0a04..76705c75f 100644
--- a/frontends/ast/genrtlil.cc
+++ b/frontends/ast/genrtlil.cc
@@ -595,6 +595,9 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
switch (type)
{
+ case AST_NONE:
+ // unallocated enum, ignore
+ break;
case AST_CONSTANT:
width_hint = max(width_hint, int(bits.size()));
if (!is_signed)
@@ -612,7 +615,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
id_ast = current_scope.at(str);
if (!id_ast)
log_file_error(filename, linenum, "Failed to resolve identifier %s for width detection!\n", str.c_str());
- if (id_ast->type == AST_PARAMETER || id_ast->type == AST_LOCALPARAM) {
+ if (id_ast->type == AST_PARAMETER || id_ast->type == AST_LOCALPARAM || id_ast->type == AST_ENUM_ITEM) {
if (id_ast->children.size() > 1 && id_ast->children[1]->range_valid) {
this_width = id_ast->children[1]->range_left - id_ast->children[1]->range_right + 1;
} else
@@ -861,6 +864,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
case AST_GENIF:
case AST_GENCASE:
case AST_PACKAGE:
+ case AST_ENUM:
case AST_MODPORT:
case AST_MODPORTMEMBER:
case AST_TYPEDEF:
@@ -1022,7 +1026,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
else
log_file_error(filename, linenum, "Identifier `%s' is implicitly declared and `default_nettype is set to none.\n", str.c_str());
}
- else if (id2ast->type == AST_PARAMETER || id2ast->type == AST_LOCALPARAM) {
+ else if (id2ast->type == AST_PARAMETER || id2ast->type == AST_LOCALPARAM || id2ast->type == AST_ENUM_ITEM) {
if (id2ast->children[0]->type != AST_CONSTANT)
log_file_error(filename, linenum, "Parameter %s does not evaluate to constant value!\n", str.c_str());
chunk = RTLIL::Const(id2ast->children[0]->bits);
diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc
index b94a8d710..9013ebe66 100644
--- a/frontends/ast/simplify.cc
+++ b/frontends/ast/simplify.cc
@@ -318,13 +318,13 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
}
// activate const folding if this is anything that must be evaluated statically (ranges, parameters, attributes, etc.)
- if (type == AST_WIRE || type == AST_PARAMETER || type == AST_LOCALPARAM || type == AST_DEFPARAM || type == AST_PARASET || type == AST_RANGE || type == AST_PREFIX || type == AST_TYPEDEF)
+ if (type == AST_WIRE || type == AST_PARAMETER || type == AST_LOCALPARAM || type == AST_ENUM_ITEM || type == AST_DEFPARAM || type == AST_PARASET || type == AST_RANGE || type == AST_PREFIX || type == AST_TYPEDEF)
const_fold = true;
- if (type == AST_IDENTIFIER && current_scope.count(str) > 0 && (current_scope[str]->type == AST_PARAMETER || current_scope[str]->type == AST_LOCALPARAM))
+ if (type == AST_IDENTIFIER && current_scope.count(str) > 0 && (current_scope[str]->type == AST_PARAMETER || current_scope[str]->type == AST_LOCALPARAM || current_scope[str]->type == AST_ENUM_ITEM))
const_fold = true;
// in certain cases a function must be evaluated constant. this is what in_param controls.
- if (type == AST_PARAMETER || type == AST_LOCALPARAM || type == AST_DEFPARAM || type == AST_PARASET || type == AST_PREFIX)
+ if (type == AST_PARAMETER || type == AST_LOCALPARAM || type == AST_LOCALPARAM || type == AST_ENUM_ITEM || type == AST_DEFPARAM || type == AST_PARASET || type == AST_PREFIX)
in_param = true;
std::map<std::string, AstNode*> backup_scope;
@@ -405,12 +405,23 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
}
this_wire_scope[node->str] = node;
}
+ // these nodes appear at the top level in a module and can define names
if (node->type == AST_PARAMETER || node->type == AST_LOCALPARAM || node->type == AST_WIRE || node->type == AST_AUTOWIRE || node->type == AST_GENVAR ||
node->type == AST_MEMORY || node->type == AST_FUNCTION || node->type == AST_TASK || node->type == AST_DPI_FUNCTION || node->type == AST_CELL ||
node->type == AST_TYPEDEF) {
backup_scope[node->str] = current_scope[node->str];
current_scope[node->str] = node;
}
+ if (node->type == AST_ENUM) {
+ for (auto enode : node->children) {
+ log_assert(enode->type==AST_ENUM_ITEM);
+ if (current_scope.count(enode->str) == 0) {
+ current_scope[enode->str] = enode;
+ }
+ // while (enode->simplify(true, false, false, 1, -1, false, true))
+ // did_something = true;
+ }
+ }
}
for (size_t i = 0; i < children.size(); i++) {
AstNode *node = children[i];
@@ -492,8 +503,21 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
}
break;
+ case AST_ENUM:
+ // log("\nENUM %d child %d\n", basic_prep, children[0]->basic_prep);
+ if (!basic_prep) {
+ for (auto item_node : children) {
+ while (!item_node->basic_prep && item_node->simplify(false, false, false, stage, -1, false, true) == true)
+ did_something = true;
+ }
+ // allocate values (called more than once)
+ allocateDefaultEnumValues();
+ }
+ break;
+
case AST_PARAMETER:
case AST_LOCALPARAM:
+ case AST_ENUM_ITEM:
while (!children[0]->basic_prep && children[0]->simplify(false, false, false, stage, -1, false, true) == true)
did_something = true;
children[0]->detectSignWidth(width_hint, sign_hint);
@@ -826,7 +850,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
// Insert clones children from template at beginning
for (int i = 0; i < GetSize(templ->children); i++)
children.insert(children.begin() + i, templ->children[i]->clone());
-
+
if (type == AST_MEMORY && GetSize(children) == 1) {
// Single-bit memories must have [0:0] range
AstNode *rng = new AstNode(AST_RANGE);
@@ -873,7 +897,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
did_something = true;
}
log_assert(!is_custom_type);
- }
+ }
// resolve constant prefixes
if (type == AST_PREFIX) {
@@ -1005,7 +1029,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
}
// trim/extend parameters
- if (type == AST_PARAMETER || type == AST_LOCALPARAM) {
+ if (type == AST_PARAMETER || type == AST_LOCALPARAM || type == AST_ENUM_ITEM) {
if (children.size() > 1 && children[1]->type == AST_RANGE) {
if (!children[1]->range_valid)
log_file_error(filename, linenum, "Non-constant width range on parameter decl.\n");
@@ -1046,10 +1070,32 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
if (type == AST_IDENTIFIER) {
if (current_scope.count(str) == 0) {
for (auto node : current_ast_mod->children) {
- if ((node->type == AST_PARAMETER || node->type == AST_LOCALPARAM || node->type == AST_WIRE || node->type == AST_AUTOWIRE || node->type == AST_GENVAR ||
- node->type == AST_MEMORY || node->type == AST_FUNCTION || node->type == AST_TASK || node->type == AST_DPI_FUNCTION) && str == node->str) {
+ //log("looking at mod scope child %s\n", type2str(node->type).c_str());
+ switch (node->type) {
+ case AST_PARAMETER:
+ case AST_LOCALPARAM:
+ case AST_WIRE:
+ case AST_AUTOWIRE:
+ case AST_GENVAR:
+ case AST_MEMORY:
+ case AST_FUNCTION:
+ case AST_TASK:
+ case AST_DPI_FUNCTION:
+ //log("found child %s, %s\n", type2str(node->type).c_str(), node->str.c_str());
+ log("add %s, type %s to scope\n", str.c_str(), type2str(node->type).c_str());
current_scope[node->str] = node;
break;
+ case AST_ENUM:
+ for (auto enum_node : node->children) {
+ log_assert(enum_node->type==AST_ENUM_ITEM);
+ if (str == enum_node->str) {
+ log("\nadding enum %s to scope\n", str.c_str());
+ current_scope[str] = enum_node;
+ }
+ }
+ break;
+ default:
+ break;
}
}
}
@@ -2482,7 +2528,7 @@ skip_dynamic_range_lvalue_expansion:;
}
for (auto child : decl->children)
- if (child->type == AST_WIRE || child->type == AST_MEMORY || child->type == AST_PARAMETER || child->type == AST_LOCALPARAM)
+ if (child->type == AST_WIRE || child->type == AST_MEMORY || child->type == AST_PARAMETER || child->type == AST_LOCALPARAM || child->type == AST_ENUM_ITEM)
{
AstNode *wire = nullptr;
@@ -2588,7 +2634,7 @@ replace_fcall_later:;
switch (type)
{
case AST_IDENTIFIER:
- if (current_scope.count(str) > 0 && (current_scope[str]->type == AST_PARAMETER || current_scope[str]->type == AST_LOCALPARAM)) {
+ if (current_scope.count(str) > 0 && (current_scope[str]->type == AST_PARAMETER || current_scope[str]->type == AST_LOCALPARAM || current_scope[str]->type == AST_ENUM_ITEM)) {
if (current_scope[str]->children[0]->type == AST_CONSTANT) {
if (children.size() != 0 && children[0]->type == AST_RANGE && children[0]->range_valid) {
std::vector<RTLIL::State> data;
@@ -3025,7 +3071,7 @@ void AstNode::expand_genblock(std::string index_var, std::string prefix, std::ma
for (size_t i = 0; i < children.size(); i++) {
AstNode *child = children[i];
if (child->type == AST_WIRE || child->type == AST_MEMORY || child->type == AST_PARAMETER || child->type == AST_LOCALPARAM ||
- child->type == AST_FUNCTION || child->type == AST_TASK || child->type == AST_CELL || child->type == AST_TYPEDEF) {
+ child->type == AST_FUNCTION || child->type == AST_TASK || child->type == AST_CELL || child->type == AST_TYPEDEF || child->type == AST_ENUM_ITEM) {
if (backup_name_map.size() == 0)
backup_name_map = name_map;
std::string new_name = prefix[0] == '\\' ? prefix.substr(1) : prefix;
@@ -3782,4 +3828,31 @@ AstNode *AstNode::eval_const_function(AstNode *fcall)
return AstNode::mkconst_bits(variables.at(str).val.bits, variables.at(str).is_signed);
}
+void AstNode::allocateDefaultEnumValues()
+{
+ log_assert(type==AST_ENUM);
+ int last_enum_int = -1;
+ for (auto node : children) {
+ log_assert(node->type==AST_ENUM_ITEM);
+ for (size_t i = 0; i < node->children.size(); i++) {
+ switch (node->children[i]->type) {
+ case AST_NONE:
+ // replace with auto-incremented constant
+ delete node->children[i];
+ node->children[i] = AstNode::mkconst_int(++last_enum_int, true);
+ break;
+ case AST_CONSTANT:
+ // explicit constant (or folded expression)
+ // TODO: can't extend 'x or 'z item
+ last_enum_int = node->children[i]->integer;
+ break;
+ default:
+ // ignore ranges
+ break;
+ }
+ // TODO: range check
+ }
+ }
+}
+
YOSYS_NAMESPACE_END