Merge pull request #1241 from YosysHQ/clifford/jsonfix

Improved JSON attr/param encoding
This commit is contained in:
David Shah 2019-08-07 10:40:38 +01:00 committed by GitHub
commit dee8f61781
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 71 additions and 36 deletions

View File

@ -83,20 +83,43 @@ struct JsonWriter
return str + " ]"; return str + " ]";
} }
void write_parameter_value(const Const &value)
{
if ((value.flags & RTLIL::ConstFlags::CONST_FLAG_STRING) != 0) {
string str = value.decode_string();
int state = 0;
for (char c : str) {
if (state == 0) {
if (c == '0' || c == '1' || c == 'x' || c == 'z')
state = 0;
else if (c == ' ')
state = 1;
else
state = 2;
} else if (state == 1 && c != ' ')
state = 2;
}
if (state < 2)
str += " ";
f << get_string(str);
} else
if (GetSize(value) == 32 && value.is_fully_def()) {
if ((value.flags & RTLIL::ConstFlags::CONST_FLAG_SIGNED) != 0)
f << stringf("%d", value.as_int());
else
f << stringf("%u", value.as_int());
} else {
f << get_string(value.as_string());
}
}
void write_parameters(const dict<IdString, Const> &parameters, bool for_module=false) void write_parameters(const dict<IdString, Const> &parameters, bool for_module=false)
{ {
bool first = true; bool first = true;
for (auto &param : parameters) { for (auto &param : parameters) {
f << stringf("%s\n", first ? "" : ","); f << stringf("%s\n", first ? "" : ",");
f << stringf(" %s%s: ", for_module ? "" : " ", get_name(param.first).c_str()); f << stringf(" %s%s: ", for_module ? "" : " ", get_name(param.first).c_str());
if ((param.second.flags & RTLIL::ConstFlags::CONST_FLAG_STRING) != 0) write_parameter_value(param.second);
f << get_string(param.second.decode_string());
else if (GetSize(param.second.bits) > 32)
f << get_string(param.second.as_string());
else if ((param.second.flags & RTLIL::ConstFlags::CONST_FLAG_SIGNED) != 0)
f << stringf("%d", param.second.as_int());
else
f << stringf("%u", param.second.as_int());
first = false; first = false;
} }
} }
@ -342,12 +365,13 @@ struct JsonBackend : public Backend {
log("Module and cell ports and nets can be single bit wide or vectors of multiple\n"); log("Module and cell ports and nets can be single bit wide or vectors of multiple\n");
log("bits. Each individual signal bit is assigned a unique integer. The <bit_vector>\n"); log("bits. Each individual signal bit is assigned a unique integer. The <bit_vector>\n");
log("values referenced above are vectors of this integers. Signal bits that are\n"); log("values referenced above are vectors of this integers. Signal bits that are\n");
log("connected to a constant driver are denoted as string \"0\" or \"1\" instead of\n"); log("connected to a constant driver are denoted as string \"0\", \"1\", \"x\", or\n");
log("a number.\n"); log("\"z\" instead of a number.\n");
log("\n"); log("\n");
log("Numeric parameter and attribute values up to 32 bits are written as decimal\n"); log("Numeric 32-bit parameter and attribute values are written as decimal values.\n");
log("values. Numbers larger than that are written as string holding the binary\n"); log("Bit verctors of different sizes, or ones containing 'x' or 'z' bits, are written\n");
log("representation of the value.\n"); log("as string holding the binary representation of the value. Strings are written\n");
log("as strings, with an appended blank in cases of strings of the form /[01xz]* */.\n");
log("\n"); log("\n");
log("For example the following Verilog code:\n"); log("For example the following Verilog code:\n");
log("\n"); log("\n");

View File

@ -25,7 +25,7 @@ struct JsonNode
{ {
char type; // S=String, N=Number, A=Array, D=Dict char type; // S=String, N=Number, A=Array, D=Dict
string data_string; string data_string;
int data_number; int64_t data_number;
vector<JsonNode*> data_array; vector<JsonNode*> data_array;
dict<string, JsonNode*> data_dict; dict<string, JsonNode*> data_dict;
vector<string> data_dict_keys; vector<string> data_dict_keys;
@ -206,6 +206,38 @@ struct JsonNode
} }
}; };
Const json_parse_attr_param_value(JsonNode *node)
{
Const value;
if (node->type == 'S') {
string &s = node->data_string;
size_t cursor = s.find_first_not_of("01xz");
if (cursor == string::npos) {
value = Const::from_string(s);
} else if (s.find_first_not_of(' ', cursor) == string::npos) {
value = Const(s.substr(0, GetSize(s)-1));
} else {
value = Const(s);
}
} else
if (node->type == 'N') {
value = Const(node->data_number, 32);
if (node->data_number < 0)
value.flags |= RTLIL::CONST_FLAG_SIGNED;
} else
if (node->type == 'A') {
log_error("JSON attribute or parameter value is an array.\n");
} else
if (node->type == 'D') {
log_error("JSON attribute or parameter value is a dict.\n");
} else {
log_abort();
}
return value;
}
void json_parse_attr_param(dict<IdString, Const> &results, JsonNode *node) void json_parse_attr_param(dict<IdString, Const> &results, JsonNode *node)
{ {
if (node->type != 'D') if (node->type != 'D')
@ -214,28 +246,7 @@ void json_parse_attr_param(dict<IdString, Const> &results, JsonNode *node)
for (auto it : node->data_dict) for (auto it : node->data_dict)
{ {
IdString key = RTLIL::escape_id(it.first.c_str()); IdString key = RTLIL::escape_id(it.first.c_str());
JsonNode *value_node = it.second; Const value = json_parse_attr_param_value(it.second);
Const value;
if (value_node->type == 'S') {
string &s = value_node->data_string;
if (s.find_first_not_of("01xz") == string::npos)
value = Const::from_string(s);
else
value = Const(s);
} else
if (value_node->type == 'N') {
value = Const(value_node->data_number, 32);
} else
if (value_node->type == 'A') {
log_error("JSON attribute or parameter value is an array.\n");
} else
if (value_node->type == 'D') {
log_error("JSON attribute or parameter value is a dict.\n");
} else {
log_abort();
}
results[key] = value; results[key] = value;
} }
} }