mirror of https://github.com/YosysHQ/yosys.git
add attributes for enumerated values in ilang
- information also useful for strongly-typed enums (not implemented) - resolves enum values in ilang part of #1594 - still need to output enums to VCD (or better yet FST) files
This commit is contained in:
parent
6320f2692b
commit
d12ba42a74
|
@ -1222,6 +1222,7 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// must be global definition
|
// must be global definition
|
||||||
|
(*it)->simplify(false, false, false, 1, -1, false, false); //process enum/other declarations
|
||||||
design->verilog_globals.push_back((*it)->clone());
|
design->verilog_globals.push_back((*it)->clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -413,6 +413,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
|
||||||
current_scope[node->str] = node;
|
current_scope[node->str] = node;
|
||||||
}
|
}
|
||||||
if (node->type == AST_ENUM) {
|
if (node->type == AST_ENUM) {
|
||||||
|
current_scope[node->str] = node;
|
||||||
for (auto enode : node->children) {
|
for (auto enode : node->children) {
|
||||||
log_assert(enode->type==AST_ENUM_ITEM);
|
log_assert(enode->type==AST_ENUM_ITEM);
|
||||||
if (current_scope.count(enode->str) == 0) {
|
if (current_scope.count(enode->str) == 0) {
|
||||||
|
@ -862,6 +863,63 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
|
||||||
range_swapped = templ->range_swapped;
|
range_swapped = templ->range_swapped;
|
||||||
range_left = templ->range_left;
|
range_left = templ->range_left;
|
||||||
range_right = templ->range_right;
|
range_right = templ->range_right;
|
||||||
|
attributes["\\wiretype"] = mkconst_str(resolved_type->str);
|
||||||
|
//check if enum
|
||||||
|
if (templ->attributes.count("\\enum_type")){
|
||||||
|
//get reference to enum node:
|
||||||
|
std::string enum_type = templ->attributes["\\enum_type"]->str.c_str();
|
||||||
|
// log("enum_type=%s (count=%lu)\n", enum_type.c_str(), current_scope.count(enum_type));
|
||||||
|
// log("current scope:\n");
|
||||||
|
// for (auto &it : current_scope)
|
||||||
|
// log(" %s\n", it.first.c_str());
|
||||||
|
log_assert(current_scope.count(enum_type) == 1);
|
||||||
|
AstNode *enum_node = current_scope.at(enum_type);
|
||||||
|
log_assert(enum_node->type == AST_ENUM);
|
||||||
|
//get width from 1st enum item:
|
||||||
|
log_assert(enum_node->children.size() >= 1);
|
||||||
|
AstNode *enum_item0 = enum_node->children[0];
|
||||||
|
log_assert(enum_item0->type == AST_ENUM_ITEM);
|
||||||
|
int width;
|
||||||
|
if (!enum_item0->range_valid)
|
||||||
|
width = 1;
|
||||||
|
else if (enum_item0->range_swapped)
|
||||||
|
width = enum_item0->range_right - enum_item0->range_left + 1;
|
||||||
|
else
|
||||||
|
width = enum_item0->range_left - enum_item0->range_right + 1;
|
||||||
|
log_assert(width > 0);
|
||||||
|
//add declared enum items:
|
||||||
|
for (auto enum_item : enum_node->children){
|
||||||
|
log_assert(enum_item->type == AST_ENUM_ITEM);
|
||||||
|
//get is_signed
|
||||||
|
bool is_signed;
|
||||||
|
if (enum_item->children.size() == 1){
|
||||||
|
is_signed = false;
|
||||||
|
} else if (enum_item->children.size() == 2){
|
||||||
|
log_assert(enum_item->children[1]->type == AST_RANGE);
|
||||||
|
is_signed = enum_item->children[1]->is_signed;
|
||||||
|
} else {
|
||||||
|
log_error("enum_item children size==%lu, expected 1 or 2 for %s (%s)\n",
|
||||||
|
enum_item->children.size(),
|
||||||
|
enum_item->str.c_str(), enum_node->str.c_str()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
//start building attribute string
|
||||||
|
std::string enum_item_str = "\\enum_";
|
||||||
|
enum_item_str.append(std::to_string(width));
|
||||||
|
enum_item_str.append("_");
|
||||||
|
//get enum item value
|
||||||
|
if(enum_item->children[0]->type != AST_CONSTANT){
|
||||||
|
log_error("expected const, got %s for %s (%s)\n",
|
||||||
|
type2str(enum_item->children[0]->type).c_str(),
|
||||||
|
enum_item->str.c_str(), enum_node->str.c_str()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
int val = enum_item->children[0]->asInt(is_signed);
|
||||||
|
enum_item_str.append(std::to_string(val));
|
||||||
|
//set attribute for available val to enum item name mappings
|
||||||
|
attributes[enum_item_str.c_str()] = mkconst_str(enum_item->str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Insert clones children from template at beginning
|
// Insert clones children from template at beginning
|
||||||
for (int i = 0; i < GetSize(templ->children); i++)
|
for (int i = 0; i < GetSize(templ->children); i++)
|
||||||
|
@ -908,6 +966,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
|
||||||
range_swapped = templ->range_swapped;
|
range_swapped = templ->range_swapped;
|
||||||
range_left = templ->range_left;
|
range_left = templ->range_left;
|
||||||
range_right = templ->range_right;
|
range_right = templ->range_right;
|
||||||
|
attributes["\\wiretype"] = mkconst_str(resolved_type->str);
|
||||||
for (auto template_child : templ->children)
|
for (auto template_child : templ->children)
|
||||||
children.push_back(template_child->clone());
|
children.push_back(template_child->clone());
|
||||||
did_something = true;
|
did_something = true;
|
||||||
|
@ -1104,10 +1163,11 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case AST_ENUM:
|
case AST_ENUM:
|
||||||
|
current_scope[node->str] = node;
|
||||||
for (auto enum_node : node->children) {
|
for (auto enum_node : node->children) {
|
||||||
log_assert(enum_node->type==AST_ENUM_ITEM);
|
log_assert(enum_node->type==AST_ENUM_ITEM);
|
||||||
if (str == enum_node->str) {
|
if (str == enum_node->str) {
|
||||||
log("\nadding enum %s to scope\n", str.c_str());
|
//log("\nadding enum item %s to scope\n", str.c_str());
|
||||||
current_scope[str] = enum_node;
|
current_scope[str] = enum_node;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2577,6 +2637,10 @@ skip_dynamic_range_lvalue_expansion:;
|
||||||
wire->is_output = false;
|
wire->is_output = false;
|
||||||
wire->is_reg = true;
|
wire->is_reg = true;
|
||||||
wire->attributes["\\nosync"] = AstNode::mkconst_int(1, false);
|
wire->attributes["\\nosync"] = AstNode::mkconst_int(1, false);
|
||||||
|
if (child->type == AST_ENUM_ITEM){
|
||||||
|
wire->attributes["\\enum_base_type"] = child->attributes["\\enum_base_type"];
|
||||||
|
|
||||||
|
}
|
||||||
wire_cache[child->str] = wire;
|
wire_cache[child->str] = wire;
|
||||||
|
|
||||||
current_ast_mod->children.push_back(wire);
|
current_ast_mod->children.push_back(wire);
|
||||||
|
@ -3109,6 +3173,7 @@ void AstNode::expand_genblock(std::string index_var, std::string prefix, std::ma
|
||||||
current_scope[new_name] = child;
|
current_scope[new_name] = child;
|
||||||
}
|
}
|
||||||
if (child->type == AST_ENUM){
|
if (child->type == AST_ENUM){
|
||||||
|
current_scope[child->str] = child;
|
||||||
for (auto enode : child->children){
|
for (auto enode : child->children){
|
||||||
log_assert(enode->type == AST_ENUM_ITEM);
|
log_assert(enode->type == AST_ENUM_ITEM);
|
||||||
if (backup_name_map.size() == 0)
|
if (backup_name_map.size() == 0)
|
||||||
|
@ -3872,6 +3937,7 @@ void AstNode::allocateDefaultEnumValues()
|
||||||
int last_enum_int = -1;
|
int last_enum_int = -1;
|
||||||
for (auto node : children) {
|
for (auto node : children) {
|
||||||
log_assert(node->type==AST_ENUM_ITEM);
|
log_assert(node->type==AST_ENUM_ITEM);
|
||||||
|
node->attributes["\\enum_base_type"] = mkconst_str(str);
|
||||||
for (size_t i = 0; i < node->children.size(); i++) {
|
for (size_t i = 0; i < node->children.size(); i++) {
|
||||||
switch (node->children[i]->type) {
|
switch (node->children[i]->type) {
|
||||||
case AST_NONE:
|
case AST_NONE:
|
||||||
|
|
|
@ -1243,9 +1243,12 @@ single_defparam_decl:
|
||||||
};
|
};
|
||||||
|
|
||||||
enum_type: TOK_ENUM {
|
enum_type: TOK_ENUM {
|
||||||
|
static int enum_count;
|
||||||
// create parent node for the enum
|
// create parent node for the enum
|
||||||
astbuf2 = new AstNode(AST_ENUM);
|
astbuf2 = new AstNode(AST_ENUM);
|
||||||
ast_stack.back()->children.push_back(astbuf2);
|
ast_stack.back()->children.push_back(astbuf2);
|
||||||
|
astbuf2->str = std::string("$enum");
|
||||||
|
astbuf2->str += std::to_string(enum_count++);
|
||||||
// create the template for the names
|
// create the template for the names
|
||||||
astbuf1 = new AstNode(AST_ENUM_ITEM);
|
astbuf1 = new AstNode(AST_ENUM_ITEM);
|
||||||
astbuf1->children.push_back(AstNode::mkconst_int(0, true));
|
astbuf1->children.push_back(AstNode::mkconst_int(0, true));
|
||||||
|
@ -1254,6 +1257,7 @@ enum_type: TOK_ENUM {
|
||||||
delete astbuf1;
|
delete astbuf1;
|
||||||
astbuf1 = tnode;
|
astbuf1 = tnode;
|
||||||
tnode->type = AST_WIRE;
|
tnode->type = AST_WIRE;
|
||||||
|
tnode->attributes["\\enum_type"] = AstNode::mkconst_str(astbuf2->str);
|
||||||
// drop constant but keep any range
|
// drop constant but keep any range
|
||||||
delete tnode->children[0];
|
delete tnode->children[0];
|
||||||
tnode->children.erase(tnode->children.begin()); }
|
tnode->children.erase(tnode->children.begin()); }
|
||||||
|
@ -1311,7 +1315,10 @@ enum_var: TOK_ID {
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
enum_decl: enum_type enum_var_list ';' { delete astbuf1; }
|
enum_decl: enum_type enum_var_list ';' {
|
||||||
|
//enum_type creates astbuf1 for use by typedef only
|
||||||
|
delete astbuf1;
|
||||||
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
wire_decl:
|
wire_decl:
|
||||||
|
|
|
@ -6,7 +6,7 @@ module enum_simple(input clk, input rst);
|
||||||
ts0, ts1, ts2, ts3
|
ts0, ts1, ts2, ts3
|
||||||
} states_t;
|
} states_t;
|
||||||
(states_t) state;
|
(states_t) state;
|
||||||
(states_t) enum_const = s1;
|
(states_t) enum_const = ts1;
|
||||||
|
|
||||||
always @(posedge clk) begin
|
always @(posedge clk) begin
|
||||||
if (rst) begin
|
if (rst) begin
|
||||||
|
@ -41,7 +41,7 @@ module enum_simple(input clk, input rst);
|
||||||
assert(state != 2'h3);
|
assert(state != 2'h3);
|
||||||
assert(s0 == '0);
|
assert(s0 == '0);
|
||||||
assert(ts0 == '0);
|
assert(ts0 == '0);
|
||||||
assert(enum_const == s1);
|
assert(enum_const == ts1);
|
||||||
end
|
end
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|
|
@ -27,7 +27,7 @@ module top;
|
||||||
end
|
end
|
||||||
|
|
||||||
(inner_type) inner_i2 = 8'h42;
|
(inner_type) inner_i2 = 8'h42;
|
||||||
(inner_type) inner_enum2 = s4;
|
(inner_enum_t) inner_enum2 = s4;
|
||||||
always @(*) assert(inner_i2 == 4'h2);
|
always @(*) assert(inner_i2 == 4'h2);
|
||||||
always @(*) assert(inner_enum2 == 3'h4);
|
always @(*) assert(inner_enum2 == 3'h4);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue