Improve libparse encapsulation

This commit is contained in:
Martin Povišer 2024-08-13 18:43:31 +02:00
parent c35f5e379c
commit 3057c13a66
5 changed files with 73 additions and 71 deletions

View File

@ -226,7 +226,7 @@ static RTLIL::SigSpec create_tristate(RTLIL::Module *module, RTLIL::SigSpec func
return cell->getPort(ID::Y); return cell->getPort(ID::Y);
} }
static void create_ff(RTLIL::Module *module, LibertyAst *node) static void create_ff(RTLIL::Module *module, const LibertyAst *node)
{ {
RTLIL::SigSpec iq_sig(module->addWire(RTLIL::escape_id(node->args.at(0)))); RTLIL::SigSpec iq_sig(module->addWire(RTLIL::escape_id(node->args.at(0))));
RTLIL::SigSpec iqn_sig(module->addWire(RTLIL::escape_id(node->args.at(1)))); RTLIL::SigSpec iqn_sig(module->addWire(RTLIL::escape_id(node->args.at(1))));
@ -303,7 +303,7 @@ static void create_ff(RTLIL::Module *module, LibertyAst *node)
log_assert(!cell->type.empty()); log_assert(!cell->type.empty());
} }
static bool create_latch(RTLIL::Module *module, LibertyAst *node, bool flag_ignore_miss_data_latch) static bool create_latch(RTLIL::Module *module, const LibertyAst *node, bool flag_ignore_miss_data_latch)
{ {
RTLIL::SigSpec iq_sig(module->addWire(RTLIL::escape_id(node->args.at(0)))); RTLIL::SigSpec iq_sig(module->addWire(RTLIL::escape_id(node->args.at(0))));
RTLIL::SigSpec iqn_sig(module->addWire(RTLIL::escape_id(node->args.at(1)))); RTLIL::SigSpec iqn_sig(module->addWire(RTLIL::escape_id(node->args.at(1))));
@ -422,7 +422,7 @@ static bool create_latch(RTLIL::Module *module, LibertyAst *node, bool flag_igno
return true; return true;
} }
void parse_type_map(std::map<std::string, std::tuple<int, int, bool>> &type_map, LibertyAst *ast) void parse_type_map(std::map<std::string, std::tuple<int, int, bool>> &type_map, const LibertyAst *ast)
{ {
for (auto type_node : ast->children) for (auto type_node : ast->children)
{ {
@ -604,7 +604,7 @@ struct LibertyFrontend : public Frontend {
for (auto node : cell->children) for (auto node : cell->children)
{ {
if (node->id == "pin" && node->args.size() == 1) { if (node->id == "pin" && node->args.size() == 1) {
LibertyAst *dir = node->find("direction"); const LibertyAst *dir = node->find("direction");
if (!dir || (dir->value != "input" && dir->value != "output" && dir->value != "inout" && dir->value != "internal")) if (!dir || (dir->value != "input" && dir->value != "output" && dir->value != "inout" && dir->value != "internal"))
{ {
if (!flag_ignore_miss_dir) if (!flag_ignore_miss_dir)
@ -625,10 +625,10 @@ struct LibertyFrontend : public Frontend {
if (!flag_lib) if (!flag_lib)
log_error("Error in cell %s: bus interfaces are only supported in -lib mode.\n", log_id(cell_name)); log_error("Error in cell %s: bus interfaces are only supported in -lib mode.\n", log_id(cell_name));
LibertyAst *dir = node->find("direction"); const LibertyAst *dir = node->find("direction");
if (dir == nullptr) { if (dir == nullptr) {
LibertyAst *pin = node->find("pin"); const LibertyAst *pin = node->find("pin");
if (pin != nullptr) if (pin != nullptr)
dir = pin->find("direction"); dir = pin->find("direction");
} }
@ -639,7 +639,7 @@ struct LibertyFrontend : public Frontend {
if (dir->value == "internal") if (dir->value == "internal")
continue; continue;
LibertyAst *bus_type_node = node->find("bus_type"); const LibertyAst *bus_type_node = node->find("bus_type");
if (!bus_type_node || !type_map.count(bus_type_node->value)) if (!bus_type_node || !type_map.count(bus_type_node->value))
log_error("Unknown or unsupported type for bus interface %s on cell %s.\n", log_error("Unknown or unsupported type for bus interface %s on cell %s.\n",
@ -681,7 +681,7 @@ struct LibertyFrontend : public Frontend {
{ {
if (node->id == "pin" && node->args.size() == 1) if (node->id == "pin" && node->args.size() == 1)
{ {
LibertyAst *dir = node->find("direction"); const LibertyAst *dir = node->find("direction");
if (flag_lib && dir->value == "internal") if (flag_lib && dir->value == "internal")
continue; continue;
@ -704,7 +704,7 @@ struct LibertyFrontend : public Frontend {
if (flag_lib) if (flag_lib)
continue; continue;
LibertyAst *func = node->find("function"); const LibertyAst *func = node->find("function");
if (func == NULL) if (func == NULL)
{ {
if (dir->value != "inout") { // allow inout with missing function, can be used for power pins if (dir->value != "inout") { // allow inout with missing function, can be used for power pins
@ -719,7 +719,7 @@ struct LibertyFrontend : public Frontend {
} }
} else { } else {
RTLIL::SigSpec out_sig = parse_func_expr(module, func->value.c_str()); RTLIL::SigSpec out_sig = parse_func_expr(module, func->value.c_str());
LibertyAst *three_state = node->find("three_state"); const LibertyAst *three_state = node->find("three_state");
if (three_state) { if (three_state) {
out_sig = create_tristate(module, out_sig, three_state->value.c_str()); out_sig = create_tristate(module, out_sig, three_state->value.c_str());
} }

View File

@ -361,7 +361,7 @@ void read_liberty_cellarea(dict<IdString, cell_area_t> &cell_area, string libert
if (cell->id != "cell" || cell->args.size() != 1) if (cell->id != "cell" || cell->args.size() != 1)
continue; continue;
LibertyAst *ar = cell->find("area"); const LibertyAst *ar = cell->find("area");
bool is_flip_flop = cell->find("ff") != nullptr; bool is_flip_flop = cell->find("ff") != nullptr;
if (ar != nullptr && !ar->value.empty()) if (ar != nullptr && !ar->value.empty())
cell_area["\\" + cell->args[0]] = {/*area=*/atof(ar->value.c_str()), is_flip_flop}; cell_area["\\" + cell->args[0]] = {/*area=*/atof(ar->value.c_str()), is_flip_flop};

View File

@ -76,7 +76,7 @@ static void logmap_all()
logmap(ID($_DFFSR_PPP_)); logmap(ID($_DFFSR_PPP_));
} }
static bool parse_pin(LibertyAst *cell, LibertyAst *attr, std::string &pin_name, bool &pin_pol) static bool parse_pin(const LibertyAst *cell, const LibertyAst *attr, std::string &pin_name, bool &pin_pol)
{ {
if (cell == nullptr || attr == nullptr || attr->value.empty()) if (cell == nullptr || attr == nullptr || attr->value.empty())
return false; return false;
@ -115,9 +115,9 @@ static bool parse_pin(LibertyAst *cell, LibertyAst *attr, std::string &pin_name,
return false; return false;
} }
static void find_cell(LibertyAst *ast, IdString cell_type, bool clkpol, bool has_reset, bool rstpol, bool rstval, std::vector<std::string> &dont_use_cells) static void find_cell(const LibertyAst *ast, IdString cell_type, bool clkpol, bool has_reset, bool rstpol, bool rstval, std::vector<std::string> &dont_use_cells)
{ {
LibertyAst *best_cell = nullptr; const LibertyAst *best_cell = nullptr;
std::map<std::string, char> best_cell_ports; std::map<std::string, char> best_cell_ports;
int best_cell_pins = 0; int best_cell_pins = 0;
bool best_cell_noninv = false; bool best_cell_noninv = false;
@ -131,7 +131,7 @@ static void find_cell(LibertyAst *ast, IdString cell_type, bool clkpol, bool has
if (cell->id != "cell" || cell->args.size() != 1) if (cell->id != "cell" || cell->args.size() != 1)
continue; continue;
LibertyAst *dn = cell->find("dont_use"); const LibertyAst *dn = cell->find("dont_use");
if (dn != nullptr && dn->value == "true") if (dn != nullptr && dn->value == "true")
continue; continue;
@ -147,7 +147,7 @@ static void find_cell(LibertyAst *ast, IdString cell_type, bool clkpol, bool has
if (dont_use) if (dont_use)
continue; continue;
LibertyAst *ff = cell->find("ff"); const LibertyAst *ff = cell->find("ff");
if (ff == nullptr) if (ff == nullptr)
continue; continue;
@ -174,7 +174,7 @@ static void find_cell(LibertyAst *ast, IdString cell_type, bool clkpol, bool has
this_cell_ports[cell_next_pin] = 'D'; this_cell_ports[cell_next_pin] = 'D';
double area = 0; double area = 0;
LibertyAst *ar = cell->find("area"); const LibertyAst *ar = cell->find("area");
if (ar != nullptr && !ar->value.empty()) if (ar != nullptr && !ar->value.empty())
area = atof(ar->value.c_str()); area = atof(ar->value.c_str());
@ -186,7 +186,7 @@ static void find_cell(LibertyAst *ast, IdString cell_type, bool clkpol, bool has
if (pin->id != "pin" || pin->args.size() != 1) if (pin->id != "pin" || pin->args.size() != 1)
continue; continue;
LibertyAst *dir = pin->find("direction"); const LibertyAst *dir = pin->find("direction");
if (dir == nullptr || dir->value == "internal") if (dir == nullptr || dir->value == "internal")
continue; continue;
num_pins++; num_pins++;
@ -194,7 +194,7 @@ static void find_cell(LibertyAst *ast, IdString cell_type, bool clkpol, bool has
if (dir->value == "input" && this_cell_ports.count(pin->args[0]) == 0) if (dir->value == "input" && this_cell_ports.count(pin->args[0]) == 0)
goto continue_cell_loop; goto continue_cell_loop;
LibertyAst *func = pin->find("function"); const LibertyAst *func = pin->find("function");
if (dir->value == "output" && func != nullptr) { if (dir->value == "output" && func != nullptr) {
std::string value = func->value; std::string value = func->value;
for (size_t pos = value.find_first_of("\" \t"); pos != std::string::npos; pos = value.find_first_of("\" \t")) for (size_t pos = value.find_first_of("\" \t"); pos != std::string::npos; pos = value.find_first_of("\" \t"))
@ -239,9 +239,9 @@ static void find_cell(LibertyAst *ast, IdString cell_type, bool clkpol, bool has
} }
} }
static void find_cell_sr(LibertyAst *ast, IdString cell_type, bool clkpol, bool setpol, bool clrpol, std::vector<std::string> &dont_use_cells) static void find_cell_sr(const LibertyAst *ast, IdString cell_type, bool clkpol, bool setpol, bool clrpol, std::vector<std::string> &dont_use_cells)
{ {
LibertyAst *best_cell = nullptr; const LibertyAst *best_cell = nullptr;
std::map<std::string, char> best_cell_ports; std::map<std::string, char> best_cell_ports;
int best_cell_pins = 0; int best_cell_pins = 0;
bool best_cell_noninv = false; bool best_cell_noninv = false;
@ -255,7 +255,7 @@ static void find_cell_sr(LibertyAst *ast, IdString cell_type, bool clkpol, bool
if (cell->id != "cell" || cell->args.size() != 1) if (cell->id != "cell" || cell->args.size() != 1)
continue; continue;
LibertyAst *dn = cell->find("dont_use"); const LibertyAst *dn = cell->find("dont_use");
if (dn != nullptr && dn->value == "true") if (dn != nullptr && dn->value == "true")
continue; continue;
@ -271,7 +271,7 @@ static void find_cell_sr(LibertyAst *ast, IdString cell_type, bool clkpol, bool
if (dont_use) if (dont_use)
continue; continue;
LibertyAst *ff = cell->find("ff"); const LibertyAst *ff = cell->find("ff");
if (ff == nullptr) if (ff == nullptr)
continue; continue;
@ -294,7 +294,7 @@ static void find_cell_sr(LibertyAst *ast, IdString cell_type, bool clkpol, bool
this_cell_ports[cell_next_pin] = 'D'; this_cell_ports[cell_next_pin] = 'D';
double area = 0; double area = 0;
LibertyAst *ar = cell->find("area"); const LibertyAst *ar = cell->find("area");
if (ar != nullptr && !ar->value.empty()) if (ar != nullptr && !ar->value.empty())
area = atof(ar->value.c_str()); area = atof(ar->value.c_str());
@ -306,7 +306,7 @@ static void find_cell_sr(LibertyAst *ast, IdString cell_type, bool clkpol, bool
if (pin->id != "pin" || pin->args.size() != 1) if (pin->id != "pin" || pin->args.size() != 1)
continue; continue;
LibertyAst *dir = pin->find("direction"); const LibertyAst *dir = pin->find("direction");
if (dir == nullptr || dir->value == "internal") if (dir == nullptr || dir->value == "internal")
continue; continue;
num_pins++; num_pins++;
@ -314,7 +314,7 @@ static void find_cell_sr(LibertyAst *ast, IdString cell_type, bool clkpol, bool
if (dir->value == "input" && this_cell_ports.count(pin->args[0]) == 0) if (dir->value == "input" && this_cell_ports.count(pin->args[0]) == 0)
goto continue_cell_loop; goto continue_cell_loop;
LibertyAst *func = pin->find("function"); const LibertyAst *func = pin->find("function");
if (dir->value == "output" && func != nullptr) { if (dir->value == "output" && func != nullptr) {
std::string value = func->value; std::string value = func->value;
for (size_t pos = value.find_first_of("\" \t"); pos != std::string::npos; pos = value.find_first_of("\" \t")) for (size_t pos = value.find_first_of("\" \t"); pos != std::string::npos; pos = value.find_first_of("\" \t"))

View File

@ -32,9 +32,6 @@
using namespace Yosys; using namespace Yosys;
std::set<std::string> LibertyAst::blacklist;
std::set<std::string> LibertyAst::whitelist;
LibertyAst::~LibertyAst() LibertyAst::~LibertyAst()
{ {
for (auto child : children) for (auto child : children)
@ -42,7 +39,7 @@ LibertyAst::~LibertyAst()
children.clear(); children.clear();
} }
LibertyAst *LibertyAst::find(std::string name) const LibertyAst *LibertyAst::find(std::string name) const
{ {
for (auto child : children) for (auto child : children)
if (child->id == name) if (child->id == name)
@ -50,7 +47,7 @@ LibertyAst *LibertyAst::find(std::string name)
return NULL; return NULL;
} }
void LibertyAst::dump(FILE *f, std::string indent, std::string path, bool path_ok) void LibertyAst::dump(FILE *f, sieve &blacklist, sieve &whitelist, std::string indent, std::string path, bool path_ok) const
{ {
if (whitelist.count(path + "/*") > 0) if (whitelist.count(path + "/*") > 0)
path_ok = true; path_ok = true;
@ -77,7 +74,7 @@ void LibertyAst::dump(FILE *f, std::string indent, std::string path, bool path_o
if (!children.empty()) { if (!children.empty()) {
fprintf(f, " {\n"); fprintf(f, " {\n");
for (size_t i = 0; i < children.size(); i++) for (size_t i = 0; i < children.size(); i++)
children[i]->dump(f, indent + " ", path, path_ok); children[i]->dump(f, blacklist, whitelist, indent + " ", path, path_ok);
fprintf(f, "%s}\n", indent.c_str()); fprintf(f, "%s}\n", indent.c_str());
} else } else
fprintf(f, " ;\n"); fprintf(f, " ;\n");
@ -406,9 +403,9 @@ void LibertyParser::error(const std::string &str)
/**** END: http://svn.clairexen.net/tools/trunk/examples/check.h ****/ /**** END: http://svn.clairexen.net/tools/trunk/examples/check.h ****/
LibertyAst *find_non_null(LibertyAst *node, const char *name) const LibertyAst *find_non_null(const LibertyAst *node, const char *name)
{ {
LibertyAst *ret = node->find(name); const LibertyAst *ret = node->find(name);
if (ret == NULL) if (ret == NULL)
fprintf(stderr, "Error: expected to find `%s' node.\n", name); fprintf(stderr, "Error: expected to find `%s' node.\n", name);
return ret; return ret;
@ -455,7 +452,7 @@ std::string func2vl(std::string str)
return str; return str;
} }
void event2vl(LibertyAst *ast, std::string &edge, std::string &expr) void event2vl(const LibertyAst *ast, std::string &edge, std::string &expr)
{ {
edge.clear(); edge.clear();
expr.clear(); expr.clear();
@ -489,7 +486,7 @@ void clear_preset_var(std::string var, std::string type)
} }
} }
void gen_verilogsim_cell(LibertyAst *ast) void gen_verilogsim_cell(const LibertyAst *ast)
{ {
if (ast->find("statetable") != NULL) if (ast->find("statetable") != NULL)
return; return;
@ -522,8 +519,8 @@ void gen_verilogsim_cell(LibertyAst *ast)
if (child->id != "pin") if (child->id != "pin")
continue; continue;
CHECK_NV(child->args.size(), == 1); CHECK_NV(child->args.size(), == 1);
LibertyAst *dir = find_non_null(child, "direction"); const LibertyAst *dir = find_non_null(child, "direction");
LibertyAst *func = child->find("function"); const LibertyAst *func = child->find("function");
printf(" %s %s;\n", dir->value.c_str(), child->args[0].c_str()); printf(" %s %s;\n", dir->value.c_str(), child->args[0].c_str());
if (func != NULL) if (func != NULL)
printf(" assign %s = %s; // %s\n", child->args[0].c_str(), func2vl(func->value).c_str(), func->value.c_str()); printf(" assign %s = %s; // %s\n", child->args[0].c_str(), func2vl(func->value).c_str(), func->value.c_str());
@ -649,7 +646,7 @@ void gen_verilogsim_cell(LibertyAst *ast)
printf("endmodule\n"); printf("endmodule\n");
} }
void gen_verilogsim(LibertyAst *ast) void gen_verilogsim(const LibertyAst *ast)
{ {
CHECK_COND(ast->id == "library"); CHECK_COND(ast->id == "library");
@ -668,6 +665,7 @@ void usage()
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
bool flag_verilogsim = false; bool flag_verilogsim = false;
std::set<std::string> whitelist, blacklist;
if (argc > 3) if (argc > 3)
usage(); usage();
@ -678,26 +676,26 @@ int main(int argc, char **argv)
flag_verilogsim = true; flag_verilogsim = true;
if (!strcmp(argv[1], "-") || !strcmp(argv[1], "-verilogsim")) if (!strcmp(argv[1], "-") || !strcmp(argv[1], "-verilogsim"))
{ {
LibertyAst::whitelist.insert("/library"); whitelist.insert("/library");
LibertyAst::whitelist.insert("/library/cell"); whitelist.insert("/library/cell");
LibertyAst::whitelist.insert("/library/cell/area"); whitelist.insert("/library/cell/area");
LibertyAst::whitelist.insert("/library/cell/cell_footprint"); whitelist.insert("/library/cell/cell_footprint");
LibertyAst::whitelist.insert("/library/cell/dont_touch"); whitelist.insert("/library/cell/dont_touch");
LibertyAst::whitelist.insert("/library/cell/dont_use"); whitelist.insert("/library/cell/dont_use");
LibertyAst::whitelist.insert("/library/cell/ff"); whitelist.insert("/library/cell/ff");
LibertyAst::whitelist.insert("/library/cell/ff/*"); whitelist.insert("/library/cell/ff/*");
LibertyAst::whitelist.insert("/library/cell/latch"); whitelist.insert("/library/cell/latch");
LibertyAst::whitelist.insert("/library/cell/latch/*"); whitelist.insert("/library/cell/latch/*");
LibertyAst::whitelist.insert("/library/cell/pin"); whitelist.insert("/library/cell/pin");
LibertyAst::whitelist.insert("/library/cell/pin/clock"); whitelist.insert("/library/cell/pin/clock");
LibertyAst::whitelist.insert("/library/cell/pin/direction"); whitelist.insert("/library/cell/pin/direction");
LibertyAst::whitelist.insert("/library/cell/pin/driver_type"); whitelist.insert("/library/cell/pin/driver_type");
LibertyAst::whitelist.insert("/library/cell/pin/function"); whitelist.insert("/library/cell/pin/function");
LibertyAst::whitelist.insert("/library/cell/pin_opposite"); whitelist.insert("/library/cell/pin_opposite");
LibertyAst::whitelist.insert("/library/cell/pin/state_function"); whitelist.insert("/library/cell/pin/state_function");
LibertyAst::whitelist.insert("/library/cell/pin/three_state"); whitelist.insert("/library/cell/pin/three_state");
LibertyAst::whitelist.insert("/library/cell/statetable"); whitelist.insert("/library/cell/statetable");
LibertyAst::whitelist.insert("/library/cell/statetable/*"); whitelist.insert("/library/cell/statetable/*");
} }
else else
{ {
@ -723,10 +721,10 @@ int main(int argc, char **argv)
if (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n' || *p == '#') { if (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n' || *p == '#') {
if (!id.empty()) { if (!id.empty()) {
if (mode == '-') if (mode == '-')
LibertyAst::blacklist.insert(id); blacklist.insert(id);
else else
if (mode == '+') if (mode == '+')
LibertyAst::whitelist.insert(id); whitelist.insert(id);
else else
goto syntax_error; goto syntax_error;
} }
@ -764,7 +762,7 @@ int main(int argc, char **argv)
if (flag_verilogsim) if (flag_verilogsim)
gen_verilogsim(parser.ast); gen_verilogsim(parser.ast);
else else
parser.ast->dump(stdout); parser.ast->dump(stdout, blacklist, whitelist);
} }
if (argc == 3) if (argc == 3)

View File

@ -33,19 +33,17 @@ namespace Yosys
std::vector<std::string> args; std::vector<std::string> args;
std::vector<LibertyAst*> children; std::vector<LibertyAst*> children;
~LibertyAst(); ~LibertyAst();
LibertyAst *find(std::string name); const LibertyAst *find(std::string name) const;
void dump(FILE *f, std::string indent = "", std::string path = "", bool path_ok = false);
static std::set<std::string> blacklist; typedef std::set<std::string> sieve;
static std::set<std::string> whitelist; void dump(FILE *f, sieve &blacklist, sieve &whitelist, std::string indent = "", std::string path = "", bool path_ok = false) const;
}; };
struct LibertyParser class LibertyParser
{ {
private:
std::istream &f; std::istream &f;
int line; int line;
LibertyAst *ast;
LibertyParser(std::istream &f) : f(f), line(1), ast(parse()) {}
~LibertyParser() { if (ast) delete ast; }
/* lexer return values: /* lexer return values:
'v': identifier, string, array range [...] -> str holds the token string 'v': identifier, string, array range [...] -> str holds the token string
@ -57,6 +55,12 @@ namespace Yosys
LibertyAst *parse(); LibertyAst *parse();
void error(); void error();
void error(const std::string &str); void error(const std::string &str);
public:
const LibertyAst *ast;
LibertyParser(std::istream &f) : f(f), line(1), ast(parse()) {}
~LibertyParser() { if (ast) delete ast; }
}; };
} }