mirror of https://github.com/YosysHQ/yosys.git
Merge pull request #4537 from povik/libparse-cleanup
Liberty parsing cleanup
This commit is contained in:
commit
a854903ff0
|
@ -53,47 +53,12 @@ static RTLIL::SigSpec parse_func_identifier(RTLIL::Module *module, const char *&
|
|||
return module->wires_.at(id);
|
||||
}
|
||||
|
||||
static RTLIL::SigSpec create_inv_cell(RTLIL::Module *module, RTLIL::SigSpec A)
|
||||
{
|
||||
RTLIL::Cell *cell = module->addCell(NEW_ID, ID($_NOT_));
|
||||
cell->setPort(ID::A, A);
|
||||
cell->setPort(ID::Y, module->addWire(NEW_ID));
|
||||
return cell->getPort(ID::Y);
|
||||
}
|
||||
|
||||
static RTLIL::SigSpec create_xor_cell(RTLIL::Module *module, RTLIL::SigSpec A, RTLIL::SigSpec B)
|
||||
{
|
||||
RTLIL::Cell *cell = module->addCell(NEW_ID, ID($_XOR_));
|
||||
cell->setPort(ID::A, A);
|
||||
cell->setPort(ID::B, B);
|
||||
cell->setPort(ID::Y, module->addWire(NEW_ID));
|
||||
return cell->getPort(ID::Y);
|
||||
}
|
||||
|
||||
static RTLIL::SigSpec create_and_cell(RTLIL::Module *module, RTLIL::SigSpec A, RTLIL::SigSpec B)
|
||||
{
|
||||
RTLIL::Cell *cell = module->addCell(NEW_ID, ID($_AND_));
|
||||
cell->setPort(ID::A, A);
|
||||
cell->setPort(ID::B, B);
|
||||
cell->setPort(ID::Y, module->addWire(NEW_ID));
|
||||
return cell->getPort(ID::Y);
|
||||
}
|
||||
|
||||
static RTLIL::SigSpec create_or_cell(RTLIL::Module *module, RTLIL::SigSpec A, RTLIL::SigSpec B)
|
||||
{
|
||||
RTLIL::Cell *cell = module->addCell(NEW_ID, ID($_OR_));
|
||||
cell->setPort(ID::A, A);
|
||||
cell->setPort(ID::B, B);
|
||||
cell->setPort(ID::Y, module->addWire(NEW_ID));
|
||||
return cell->getPort(ID::Y);
|
||||
}
|
||||
|
||||
static bool parse_func_reduce(RTLIL::Module *module, std::vector<token_t> &stack, token_t next_token)
|
||||
{
|
||||
int top = int(stack.size())-1;
|
||||
|
||||
if (0 <= top-1 && stack[top].type == 0 && stack[top-1].type == '!') {
|
||||
token_t t = token_t(0, create_inv_cell(module, stack[top].sig));
|
||||
token_t t = token_t(0, module->NotGate(NEW_ID, stack[top].sig));
|
||||
stack.pop_back();
|
||||
stack.pop_back();
|
||||
stack.push_back(t);
|
||||
|
@ -101,7 +66,7 @@ static bool parse_func_reduce(RTLIL::Module *module, std::vector<token_t> &stack
|
|||
}
|
||||
|
||||
if (0 <= top-1 && stack[top].type == '\'' && stack[top-1].type == 0) {
|
||||
token_t t = token_t(0, create_inv_cell(module, stack[top-1].sig));
|
||||
token_t t = token_t(0, module->NotGate(NEW_ID, stack[top-1].sig));
|
||||
stack.pop_back();
|
||||
stack.pop_back();
|
||||
stack.push_back(t);
|
||||
|
@ -116,7 +81,7 @@ static bool parse_func_reduce(RTLIL::Module *module, std::vector<token_t> &stack
|
|||
}
|
||||
|
||||
if (0 <= top-2 && stack[top-2].type == 1 && stack[top-1].type == '^' && stack[top].type == 1) {
|
||||
token_t t = token_t(1, create_xor_cell(module, stack[top-2].sig, stack[top].sig));
|
||||
token_t t = token_t(1, module->XorGate(NEW_ID, stack[top-2].sig, stack[top].sig));
|
||||
stack.pop_back();
|
||||
stack.pop_back();
|
||||
stack.pop_back();
|
||||
|
@ -132,7 +97,7 @@ static bool parse_func_reduce(RTLIL::Module *module, std::vector<token_t> &stack
|
|||
}
|
||||
|
||||
if (0 <= top-1 && stack[top-1].type == 2 && stack[top].type == 2) {
|
||||
token_t t = token_t(2, create_and_cell(module, stack[top-1].sig, stack[top].sig));
|
||||
token_t t = token_t(2, module->AndGate(NEW_ID, stack[top-1].sig, stack[top].sig));
|
||||
stack.pop_back();
|
||||
stack.pop_back();
|
||||
stack.push_back(t);
|
||||
|
@ -140,7 +105,7 @@ static bool parse_func_reduce(RTLIL::Module *module, std::vector<token_t> &stack
|
|||
}
|
||||
|
||||
if (0 <= top-2 && stack[top-2].type == 2 && (stack[top-1].type == '*' || stack[top-1].type == '&') && stack[top].type == 2) {
|
||||
token_t t = token_t(2, create_and_cell(module, stack[top-2].sig, stack[top].sig));
|
||||
token_t t = token_t(2, module->AndGate(NEW_ID, stack[top-2].sig, stack[top].sig));
|
||||
stack.pop_back();
|
||||
stack.pop_back();
|
||||
stack.pop_back();
|
||||
|
@ -156,7 +121,7 @@ static bool parse_func_reduce(RTLIL::Module *module, std::vector<token_t> &stack
|
|||
}
|
||||
|
||||
if (0 <= top-2 && stack[top-2].type == 3 && (stack[top-1].type == '+' || stack[top-1].type == '|') && stack[top].type == 3) {
|
||||
token_t t = token_t(3, create_or_cell(module, stack[top-2].sig, stack[top].sig));
|
||||
token_t t = token_t(3, module->OrGate(NEW_ID, stack[top-2].sig, stack[top].sig));
|
||||
stack.pop_back();
|
||||
stack.pop_back();
|
||||
stack.pop_back();
|
||||
|
@ -221,12 +186,12 @@ static RTLIL::SigSpec create_tristate(RTLIL::Module *module, RTLIL::SigSpec func
|
|||
RTLIL::Cell *cell = module->addCell(NEW_ID, ID($tribuf));
|
||||
cell->setParam(ID::WIDTH, GetSize(func));
|
||||
cell->setPort(ID::A, func);
|
||||
cell->setPort(ID::EN, create_inv_cell(module, three_state));
|
||||
cell->setPort(ID::EN, module->NotGate(NEW_ID, three_state));
|
||||
cell->setPort(ID::Y, module->addWire(NEW_ID));
|
||||
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 iqn_sig(module->addWire(RTLIL::escape_id(node->args.at(1))));
|
||||
|
@ -303,7 +268,7 @@ static void create_ff(RTLIL::Module *module, LibertyAst *node)
|
|||
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 iqn_sig(module->addWire(RTLIL::escape_id(node->args.at(1))));
|
||||
|
@ -422,7 +387,7 @@ static bool create_latch(RTLIL::Module *module, LibertyAst *node, bool flag_igno
|
|||
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)
|
||||
{
|
||||
|
@ -604,7 +569,7 @@ struct LibertyFrontend : public Frontend {
|
|||
for (auto node : cell->children)
|
||||
{
|
||||
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 (!flag_ignore_miss_dir)
|
||||
|
@ -625,10 +590,10 @@ struct LibertyFrontend : public Frontend {
|
|||
if (!flag_lib)
|
||||
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) {
|
||||
LibertyAst *pin = node->find("pin");
|
||||
const LibertyAst *pin = node->find("pin");
|
||||
if (pin != nullptr)
|
||||
dir = pin->find("direction");
|
||||
}
|
||||
|
@ -639,7 +604,7 @@ struct LibertyFrontend : public Frontend {
|
|||
if (dir->value == "internal")
|
||||
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))
|
||||
log_error("Unknown or unsupported type for bus interface %s on cell %s.\n",
|
||||
|
@ -681,7 +646,7 @@ struct LibertyFrontend : public Frontend {
|
|||
{
|
||||
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")
|
||||
continue;
|
||||
|
@ -704,7 +669,7 @@ struct LibertyFrontend : public Frontend {
|
|||
if (flag_lib)
|
||||
continue;
|
||||
|
||||
LibertyAst *func = node->find("function");
|
||||
const LibertyAst *func = node->find("function");
|
||||
if (func == NULL)
|
||||
{
|
||||
if (dir->value != "inout") { // allow inout with missing function, can be used for power pins
|
||||
|
@ -719,7 +684,7 @@ struct LibertyFrontend : public Frontend {
|
|||
}
|
||||
} else {
|
||||
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) {
|
||||
out_sig = create_tristate(module, out_sig, three_state->value.c_str());
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
continue;
|
||||
|
||||
LibertyAst *ar = cell->find("area");
|
||||
const LibertyAst *ar = cell->find("area");
|
||||
bool is_flip_flop = cell->find("ff") != nullptr;
|
||||
if (ar != nullptr && !ar->value.empty())
|
||||
cell_area["\\" + cell->args[0]] = {/*area=*/atof(ar->value.c_str()), is_flip_flop};
|
||||
|
|
|
@ -76,7 +76,7 @@ static void logmap_all()
|
|||
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())
|
||||
return false;
|
||||
|
@ -115,9 +115,9 @@ static bool parse_pin(LibertyAst *cell, LibertyAst *attr, std::string &pin_name,
|
|||
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;
|
||||
int best_cell_pins = 0;
|
||||
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)
|
||||
continue;
|
||||
|
||||
LibertyAst *dn = cell->find("dont_use");
|
||||
const LibertyAst *dn = cell->find("dont_use");
|
||||
if (dn != nullptr && dn->value == "true")
|
||||
continue;
|
||||
|
||||
|
@ -147,7 +147,7 @@ static void find_cell(LibertyAst *ast, IdString cell_type, bool clkpol, bool has
|
|||
if (dont_use)
|
||||
continue;
|
||||
|
||||
LibertyAst *ff = cell->find("ff");
|
||||
const LibertyAst *ff = cell->find("ff");
|
||||
if (ff == nullptr)
|
||||
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';
|
||||
|
||||
double area = 0;
|
||||
LibertyAst *ar = cell->find("area");
|
||||
const LibertyAst *ar = cell->find("area");
|
||||
if (ar != nullptr && !ar->value.empty())
|
||||
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)
|
||||
continue;
|
||||
|
||||
LibertyAst *dir = pin->find("direction");
|
||||
const LibertyAst *dir = pin->find("direction");
|
||||
if (dir == nullptr || dir->value == "internal")
|
||||
continue;
|
||||
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)
|
||||
goto continue_cell_loop;
|
||||
|
||||
LibertyAst *func = pin->find("function");
|
||||
const LibertyAst *func = pin->find("function");
|
||||
if (dir->value == "output" && func != nullptr) {
|
||||
std::string value = func->value;
|
||||
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;
|
||||
int best_cell_pins = 0;
|
||||
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)
|
||||
continue;
|
||||
|
||||
LibertyAst *dn = cell->find("dont_use");
|
||||
const LibertyAst *dn = cell->find("dont_use");
|
||||
if (dn != nullptr && dn->value == "true")
|
||||
continue;
|
||||
|
||||
|
@ -271,7 +271,7 @@ static void find_cell_sr(LibertyAst *ast, IdString cell_type, bool clkpol, bool
|
|||
if (dont_use)
|
||||
continue;
|
||||
|
||||
LibertyAst *ff = cell->find("ff");
|
||||
const LibertyAst *ff = cell->find("ff");
|
||||
if (ff == nullptr)
|
||||
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';
|
||||
|
||||
double area = 0;
|
||||
LibertyAst *ar = cell->find("area");
|
||||
const LibertyAst *ar = cell->find("area");
|
||||
if (ar != nullptr && !ar->value.empty())
|
||||
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)
|
||||
continue;
|
||||
|
||||
LibertyAst *dir = pin->find("direction");
|
||||
const LibertyAst *dir = pin->find("direction");
|
||||
if (dir == nullptr || dir->value == "internal")
|
||||
continue;
|
||||
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)
|
||||
goto continue_cell_loop;
|
||||
|
||||
LibertyAst *func = pin->find("function");
|
||||
const LibertyAst *func = pin->find("function");
|
||||
if (dir->value == "output" && func != nullptr) {
|
||||
std::string value = func->value;
|
||||
for (size_t pos = value.find_first_of("\" \t"); pos != std::string::npos; pos = value.find_first_of("\" \t"))
|
||||
|
|
|
@ -32,9 +32,6 @@
|
|||
|
||||
using namespace Yosys;
|
||||
|
||||
std::set<std::string> LibertyAst::blacklist;
|
||||
std::set<std::string> LibertyAst::whitelist;
|
||||
|
||||
LibertyAst::~LibertyAst()
|
||||
{
|
||||
for (auto child : children)
|
||||
|
@ -42,7 +39,7 @@ LibertyAst::~LibertyAst()
|
|||
children.clear();
|
||||
}
|
||||
|
||||
LibertyAst *LibertyAst::find(std::string name)
|
||||
const LibertyAst *LibertyAst::find(std::string name) const
|
||||
{
|
||||
for (auto child : children)
|
||||
if (child->id == name)
|
||||
|
@ -50,7 +47,7 @@ LibertyAst *LibertyAst::find(std::string name)
|
|||
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)
|
||||
path_ok = true;
|
||||
|
@ -77,7 +74,7 @@ void LibertyAst::dump(FILE *f, std::string indent, std::string path, bool path_o
|
|||
if (!children.empty()) {
|
||||
fprintf(f, " {\n");
|
||||
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());
|
||||
} else
|
||||
fprintf(f, " ;\n");
|
||||
|
@ -406,9 +403,9 @@ void LibertyParser::error(const std::string &str)
|
|||
|
||||
/**** 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)
|
||||
fprintf(stderr, "Error: expected to find `%s' node.\n", name);
|
||||
return ret;
|
||||
|
@ -455,7 +452,7 @@ std::string func2vl(std::string 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();
|
||||
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)
|
||||
return;
|
||||
|
@ -522,8 +519,8 @@ void gen_verilogsim_cell(LibertyAst *ast)
|
|||
if (child->id != "pin")
|
||||
continue;
|
||||
CHECK_NV(child->args.size(), == 1);
|
||||
LibertyAst *dir = find_non_null(child, "direction");
|
||||
LibertyAst *func = child->find("function");
|
||||
const LibertyAst *dir = find_non_null(child, "direction");
|
||||
const LibertyAst *func = child->find("function");
|
||||
printf(" %s %s;\n", dir->value.c_str(), child->args[0].c_str());
|
||||
if (func != NULL)
|
||||
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");
|
||||
}
|
||||
|
||||
void gen_verilogsim(LibertyAst *ast)
|
||||
void gen_verilogsim(const LibertyAst *ast)
|
||||
{
|
||||
CHECK_COND(ast->id == "library");
|
||||
|
||||
|
@ -668,6 +665,7 @@ void usage()
|
|||
int main(int argc, char **argv)
|
||||
{
|
||||
bool flag_verilogsim = false;
|
||||
std::set<std::string> whitelist, blacklist;
|
||||
|
||||
if (argc > 3)
|
||||
usage();
|
||||
|
@ -678,26 +676,26 @@ int main(int argc, char **argv)
|
|||
flag_verilogsim = true;
|
||||
if (!strcmp(argv[1], "-") || !strcmp(argv[1], "-verilogsim"))
|
||||
{
|
||||
LibertyAst::whitelist.insert("/library");
|
||||
LibertyAst::whitelist.insert("/library/cell");
|
||||
LibertyAst::whitelist.insert("/library/cell/area");
|
||||
LibertyAst::whitelist.insert("/library/cell/cell_footprint");
|
||||
LibertyAst::whitelist.insert("/library/cell/dont_touch");
|
||||
LibertyAst::whitelist.insert("/library/cell/dont_use");
|
||||
LibertyAst::whitelist.insert("/library/cell/ff");
|
||||
LibertyAst::whitelist.insert("/library/cell/ff/*");
|
||||
LibertyAst::whitelist.insert("/library/cell/latch");
|
||||
LibertyAst::whitelist.insert("/library/cell/latch/*");
|
||||
LibertyAst::whitelist.insert("/library/cell/pin");
|
||||
LibertyAst::whitelist.insert("/library/cell/pin/clock");
|
||||
LibertyAst::whitelist.insert("/library/cell/pin/direction");
|
||||
LibertyAst::whitelist.insert("/library/cell/pin/driver_type");
|
||||
LibertyAst::whitelist.insert("/library/cell/pin/function");
|
||||
LibertyAst::whitelist.insert("/library/cell/pin_opposite");
|
||||
LibertyAst::whitelist.insert("/library/cell/pin/state_function");
|
||||
LibertyAst::whitelist.insert("/library/cell/pin/three_state");
|
||||
LibertyAst::whitelist.insert("/library/cell/statetable");
|
||||
LibertyAst::whitelist.insert("/library/cell/statetable/*");
|
||||
whitelist.insert("/library");
|
||||
whitelist.insert("/library/cell");
|
||||
whitelist.insert("/library/cell/area");
|
||||
whitelist.insert("/library/cell/cell_footprint");
|
||||
whitelist.insert("/library/cell/dont_touch");
|
||||
whitelist.insert("/library/cell/dont_use");
|
||||
whitelist.insert("/library/cell/ff");
|
||||
whitelist.insert("/library/cell/ff/*");
|
||||
whitelist.insert("/library/cell/latch");
|
||||
whitelist.insert("/library/cell/latch/*");
|
||||
whitelist.insert("/library/cell/pin");
|
||||
whitelist.insert("/library/cell/pin/clock");
|
||||
whitelist.insert("/library/cell/pin/direction");
|
||||
whitelist.insert("/library/cell/pin/driver_type");
|
||||
whitelist.insert("/library/cell/pin/function");
|
||||
whitelist.insert("/library/cell/pin_opposite");
|
||||
whitelist.insert("/library/cell/pin/state_function");
|
||||
whitelist.insert("/library/cell/pin/three_state");
|
||||
whitelist.insert("/library/cell/statetable");
|
||||
whitelist.insert("/library/cell/statetable/*");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -723,10 +721,10 @@ int main(int argc, char **argv)
|
|||
if (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n' || *p == '#') {
|
||||
if (!id.empty()) {
|
||||
if (mode == '-')
|
||||
LibertyAst::blacklist.insert(id);
|
||||
blacklist.insert(id);
|
||||
else
|
||||
if (mode == '+')
|
||||
LibertyAst::whitelist.insert(id);
|
||||
whitelist.insert(id);
|
||||
else
|
||||
goto syntax_error;
|
||||
}
|
||||
|
@ -764,7 +762,7 @@ int main(int argc, char **argv)
|
|||
if (flag_verilogsim)
|
||||
gen_verilogsim(parser.ast);
|
||||
else
|
||||
parser.ast->dump(stdout);
|
||||
parser.ast->dump(stdout, blacklist, whitelist);
|
||||
}
|
||||
|
||||
if (argc == 3)
|
||||
|
|
|
@ -33,32 +33,35 @@ namespace Yosys
|
|||
std::vector<std::string> args;
|
||||
std::vector<LibertyAst*> children;
|
||||
~LibertyAst();
|
||||
LibertyAst *find(std::string name);
|
||||
void dump(FILE *f, std::string indent = "", std::string path = "", bool path_ok = false);
|
||||
static std::set<std::string> blacklist;
|
||||
static std::set<std::string> whitelist;
|
||||
const LibertyAst *find(std::string name) const;
|
||||
|
||||
typedef std::set<std::string> sieve;
|
||||
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;
|
||||
int line;
|
||||
LibertyAst *ast;
|
||||
LibertyParser(std::istream &f) : f(f), line(1), ast(parse()) {}
|
||||
~LibertyParser() { if (ast) delete ast; }
|
||||
|
||||
/* lexer return values:
|
||||
'v': identifier, string, array range [...] -> str holds the token string
|
||||
'n': newline
|
||||
anything else is a single character.
|
||||
*/
|
||||
|
||||
/* lexer return values:
|
||||
'v': identifier, string, array range [...] -> str holds the token string
|
||||
'n': newline
|
||||
anything else is a single character.
|
||||
*/
|
||||
int lexer(std::string &str);
|
||||
|
||||
LibertyAst *parse();
|
||||
LibertyAst *parse();
|
||||
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; }
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1,2 +1,4 @@
|
|||
*.log
|
||||
test.ys
|
||||
*.filtered
|
||||
*.verilogsim
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
library(ls05_stdcells) {
|
||||
cell(XNOR2X1) {
|
||||
area : 206080.0 ;
|
||||
pin(B) {
|
||||
direction : input ;
|
||||
}
|
||||
pin(A) {
|
||||
direction : input ;
|
||||
}
|
||||
pin(Y) {
|
||||
direction : output ;
|
||||
function : !(B&!A|!B&A) ;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
module XNOR2X1 (B, A, Y);
|
||||
input B;
|
||||
input A;
|
||||
output Y;
|
||||
assign Y = !(B&!A|!B&A); // !(B&!A|!B&A)
|
||||
endmodule
|
|
@ -0,0 +1,8 @@
|
|||
library(supergate) {
|
||||
cell(SRAM) {
|
||||
area : 1 ;
|
||||
pin(CE1) {
|
||||
direction : input ;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
module SRAM (CE1);
|
||||
input CE1;
|
||||
endmodule
|
|
@ -0,0 +1,4 @@
|
|||
library(fake) {
|
||||
cell(bugbad) {
|
||||
}
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
module bugbad ();
|
||||
endmodule
|
|
@ -0,0 +1,211 @@
|
|||
library(supergate) {
|
||||
cell(inv) {
|
||||
area : 1 ;
|
||||
pin(A) {
|
||||
direction : input ;
|
||||
}
|
||||
pin(Y) {
|
||||
direction : output ;
|
||||
function : A' ;
|
||||
}
|
||||
}
|
||||
cell(tri_inv) {
|
||||
area : 4 ;
|
||||
pin(A) {
|
||||
direction : input ;
|
||||
}
|
||||
pin(S) {
|
||||
direction : input ;
|
||||
}
|
||||
pin(Z) {
|
||||
direction : output ;
|
||||
function : A' ;
|
||||
}
|
||||
}
|
||||
cell(buffer) {
|
||||
area : 5 ;
|
||||
pin(A) {
|
||||
direction : input ;
|
||||
}
|
||||
pin(Y) {
|
||||
direction : output ;
|
||||
function : A ;
|
||||
}
|
||||
}
|
||||
cell(nand2) {
|
||||
area : 3 ;
|
||||
pin(A) {
|
||||
direction : input ;
|
||||
}
|
||||
pin(B) {
|
||||
direction : input ;
|
||||
}
|
||||
pin(Y) {
|
||||
direction : output ;
|
||||
function : (A * B)' ;
|
||||
}
|
||||
}
|
||||
cell(nor2) {
|
||||
area : 3 ;
|
||||
pin(A) {
|
||||
direction : input ;
|
||||
}
|
||||
pin(B) {
|
||||
direction : input ;
|
||||
}
|
||||
pin(Y) {
|
||||
direction : output ;
|
||||
function : (A + B)' ;
|
||||
}
|
||||
}
|
||||
cell(xor2) {
|
||||
area : 6 ;
|
||||
pin(A) {
|
||||
direction : input ;
|
||||
}
|
||||
pin(B) {
|
||||
direction : input ;
|
||||
}
|
||||
pin(Y) {
|
||||
direction : output ;
|
||||
function : (A *B') + (A' * B) ;
|
||||
}
|
||||
}
|
||||
cell(imux2) {
|
||||
area : 5 ;
|
||||
pin(A) {
|
||||
direction : input ;
|
||||
}
|
||||
pin(B) {
|
||||
direction : input ;
|
||||
}
|
||||
pin(S) {
|
||||
direction : input ;
|
||||
}
|
||||
pin(Y) {
|
||||
direction : output ;
|
||||
function : ( (A * S) + (B * S') )' ;
|
||||
}
|
||||
}
|
||||
cell(dff) {
|
||||
area : 6 ;
|
||||
ff(IQ, IQN) {
|
||||
next_state : D ;
|
||||
clocked_on : CLK ;
|
||||
clear : RESET ;
|
||||
preset : PRESET ;
|
||||
clear_preset_var1 : L ;
|
||||
clear_preset_var2 : L ;
|
||||
}
|
||||
pin(D) {
|
||||
direction : input ;
|
||||
}
|
||||
pin(CLK) {
|
||||
direction : input ;
|
||||
}
|
||||
pin(RESET) {
|
||||
direction : input ;
|
||||
}
|
||||
pin(PRESET) {
|
||||
direction : input ;
|
||||
}
|
||||
pin(Q) {
|
||||
direction : output ;
|
||||
function : IQ ;
|
||||
}
|
||||
pin(QN) {
|
||||
direction : output ;
|
||||
function : IQN ;
|
||||
}
|
||||
}
|
||||
cell(latch) {
|
||||
area : 5 ;
|
||||
latch(IQ, IQN) {
|
||||
enable : G ;
|
||||
data_in : D ;
|
||||
}
|
||||
pin(D) {
|
||||
direction : input ;
|
||||
}
|
||||
pin(G) {
|
||||
direction : input ;
|
||||
}
|
||||
pin(Q) {
|
||||
direction : output ;
|
||||
function : IQ ;
|
||||
}
|
||||
pin(QN) {
|
||||
direction : output ;
|
||||
function : IQN ;
|
||||
}
|
||||
}
|
||||
cell(aoi211) {
|
||||
area : 3 ;
|
||||
pin(A) {
|
||||
direction : input ;
|
||||
}
|
||||
pin(B) {
|
||||
direction : input ;
|
||||
}
|
||||
pin(C) {
|
||||
direction : input ;
|
||||
}
|
||||
pin(Y) {
|
||||
direction : output ;
|
||||
function : ((A * B) + C)' ;
|
||||
}
|
||||
}
|
||||
cell(oai211) {
|
||||
area : 3 ;
|
||||
pin(A) {
|
||||
direction : input ;
|
||||
}
|
||||
pin(B) {
|
||||
direction : input ;
|
||||
}
|
||||
pin(C) {
|
||||
direction : input ;
|
||||
}
|
||||
pin(Y) {
|
||||
direction : output ;
|
||||
function : ((A + B) * C)' ;
|
||||
}
|
||||
}
|
||||
cell(halfadder) {
|
||||
area : 5 ;
|
||||
pin(A) {
|
||||
direction : input ;
|
||||
}
|
||||
pin(B) {
|
||||
direction : input ;
|
||||
}
|
||||
pin(C) {
|
||||
direction : output ;
|
||||
function : (A * B) ;
|
||||
}
|
||||
pin(Y) {
|
||||
direction : output ;
|
||||
function : (A *B') + (A' * B) ;
|
||||
}
|
||||
}
|
||||
cell(fulladder) {
|
||||
area : 8 ;
|
||||
pin(A) {
|
||||
direction : input ;
|
||||
}
|
||||
pin(B) {
|
||||
direction : input ;
|
||||
}
|
||||
pin(CI) {
|
||||
direction : input ;
|
||||
}
|
||||
pin(CO) {
|
||||
direction : output ;
|
||||
function : (((A * B)+(B * CI))+(CI * A)) ;
|
||||
}
|
||||
pin(Y) {
|
||||
direction : output ;
|
||||
function : ((A^B)^CI) ;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,117 @@
|
|||
module inv (A, Y);
|
||||
input A;
|
||||
output Y;
|
||||
assign Y = ~A; // A'
|
||||
endmodule
|
||||
module tri_inv (A, S, Z);
|
||||
input A;
|
||||
input S;
|
||||
output Z;
|
||||
assign Z = ~A; // A'
|
||||
endmodule
|
||||
module buffer (A, Y);
|
||||
input A;
|
||||
output Y;
|
||||
assign Y = A; // A
|
||||
endmodule
|
||||
module nand2 (A, B, Y);
|
||||
input A;
|
||||
input B;
|
||||
output Y;
|
||||
assign Y = ~(A&B); // (A * B)'
|
||||
endmodule
|
||||
module nor2 (A, B, Y);
|
||||
input A;
|
||||
input B;
|
||||
output Y;
|
||||
assign Y = ~(A|B); // (A + B)'
|
||||
endmodule
|
||||
module xor2 (A, B, Y);
|
||||
input A;
|
||||
input B;
|
||||
output Y;
|
||||
assign Y = (A&~B)|(~A&B); // (A *B') + (A' * B)
|
||||
endmodule
|
||||
module imux2 (A, B, S, Y);
|
||||
input A;
|
||||
input B;
|
||||
input S;
|
||||
output Y;
|
||||
assign Y = ~(&(A&S)|(B&~S)&); // ( (A * S) + (B * S') )'
|
||||
endmodule
|
||||
module dff (D, CLK, RESET, PRESET, Q, QN);
|
||||
reg IQ, IQN;
|
||||
input D;
|
||||
input CLK;
|
||||
input RESET;
|
||||
input PRESET;
|
||||
output Q;
|
||||
assign Q = IQ; // IQ
|
||||
output QN;
|
||||
assign QN = IQN; // IQN
|
||||
always @(posedge CLK, posedge RESET, posedge PRESET) begin
|
||||
if ((RESET) && (PRESET)) begin
|
||||
IQ <= 0;
|
||||
IQN <= 0;
|
||||
end
|
||||
else if (RESET) begin
|
||||
IQ <= 0;
|
||||
IQN <= 1;
|
||||
end
|
||||
else if (PRESET) begin
|
||||
IQ <= 1;
|
||||
IQN <= 0;
|
||||
end
|
||||
else begin
|
||||
// D
|
||||
IQ <= D;
|
||||
IQN <= ~(D);
|
||||
end
|
||||
end
|
||||
endmodule
|
||||
module latch (D, G, Q, QN);
|
||||
reg IQ, IQN;
|
||||
input D;
|
||||
input G;
|
||||
output Q;
|
||||
assign Q = IQ; // IQ
|
||||
output QN;
|
||||
assign QN = IQN; // IQN
|
||||
always @* begin
|
||||
if (G) begin
|
||||
IQ <= D;
|
||||
IQN <= ~(D);
|
||||
end
|
||||
end
|
||||
endmodule
|
||||
module aoi211 (A, B, C, Y);
|
||||
input A;
|
||||
input B;
|
||||
input C;
|
||||
output Y;
|
||||
assign Y = ~((A&B)|C); // ((A * B) + C)'
|
||||
endmodule
|
||||
module oai211 (A, B, C, Y);
|
||||
input A;
|
||||
input B;
|
||||
input C;
|
||||
output Y;
|
||||
assign Y = ~((A|B)&C); // ((A + B) * C)'
|
||||
endmodule
|
||||
module halfadder (A, B, C, Y);
|
||||
input A;
|
||||
input B;
|
||||
output C;
|
||||
assign C = (A&B); // (A * B)
|
||||
output Y;
|
||||
assign Y = (A&~B)|(~A&B); // (A *B') + (A' * B)
|
||||
endmodule
|
||||
module fulladder (A, B, CI, CO, Y);
|
||||
input A;
|
||||
input B;
|
||||
input CI;
|
||||
output CO;
|
||||
assign CO = (((A&B)|(B&CI))|(CI&A)); // (((A * B)+(B * CI))+(CI * A))
|
||||
output Y;
|
||||
assign Y = ((A^B)^CI); // ((A^B)^CI)
|
||||
endmodule
|
|
@ -0,0 +1,117 @@
|
|||
module inv (A, Y);
|
||||
input A;
|
||||
output Y;
|
||||
assign Y = ~A; // A'
|
||||
endmodule
|
||||
module tri_inv (A, S, Z);
|
||||
input A;
|
||||
input S;
|
||||
output Z;
|
||||
assign Z = ~A; // A'
|
||||
endmodule
|
||||
module buffer (A, Y);
|
||||
input A;
|
||||
output Y;
|
||||
assign Y = A; // A
|
||||
endmodule
|
||||
module nand2 (A, B, Y);
|
||||
input A;
|
||||
input B;
|
||||
output Y;
|
||||
assign Y = ~(A&B); // (A * B)'
|
||||
endmodule
|
||||
module nor2 (A, B, Y);
|
||||
input A;
|
||||
input B;
|
||||
output Y;
|
||||
assign Y = ~(A|B); // (A + B)'
|
||||
endmodule
|
||||
module xor2 (A, B, Y);
|
||||
input A;
|
||||
input B;
|
||||
output Y;
|
||||
assign Y = (A&~B)|(~A&B); // (A *B') + (A' * B)
|
||||
endmodule
|
||||
module imux2 (A, B, S, Y);
|
||||
input A;
|
||||
input B;
|
||||
input S;
|
||||
output Y;
|
||||
assign Y = ~(&(A&S)|(B&~S)&); // ( (A * S) + (B * S') )'
|
||||
endmodule
|
||||
module dff (D, CLK, RESET, PRESET, Q, QN);
|
||||
reg IQ, IQN;
|
||||
input D;
|
||||
input CLK;
|
||||
input RESET;
|
||||
input PRESET;
|
||||
output Q;
|
||||
assign Q = IQ; // IQ
|
||||
output QN;
|
||||
assign QN = IQN; // IQN
|
||||
always @(posedge CLK, posedge RESET, posedge PRESET) begin
|
||||
if ((RESET) && (PRESET)) begin
|
||||
IQ <= 0;
|
||||
IQN <= 0;
|
||||
end
|
||||
else if (RESET) begin
|
||||
IQ <= 0;
|
||||
IQN <= 1;
|
||||
end
|
||||
else if (PRESET) begin
|
||||
IQ <= 1;
|
||||
IQN <= 0;
|
||||
end
|
||||
else begin
|
||||
// D
|
||||
IQ <= D;
|
||||
IQN <= ~(D);
|
||||
end
|
||||
end
|
||||
endmodule
|
||||
module latch (D, G, Q, QN);
|
||||
reg IQ, IQN;
|
||||
input D;
|
||||
input G;
|
||||
output Q;
|
||||
assign Q = IQ; // IQ
|
||||
output QN;
|
||||
assign QN = IQN; // IQN
|
||||
always @* begin
|
||||
if (G) begin
|
||||
IQ <= D;
|
||||
IQN <= ~(D);
|
||||
end
|
||||
end
|
||||
endmodule
|
||||
module aoi211 (A, B, C, Y);
|
||||
input A;
|
||||
input B;
|
||||
input C;
|
||||
output Y;
|
||||
assign Y = ~((A&B)|C); // ((A * B) + C)'
|
||||
endmodule
|
||||
module oai211 (A, B, C, Y);
|
||||
input A;
|
||||
input B;
|
||||
input C;
|
||||
output Y;
|
||||
assign Y = ~((A|B)&C); // ((A + B) * C)'
|
||||
endmodule
|
||||
module halfadder (A, B, C, Y);
|
||||
input A;
|
||||
input B;
|
||||
output C;
|
||||
assign C = (A&B); // (A * B)
|
||||
output Y;
|
||||
assign Y = (A&~B)|(~A&B); // (A *B') + (A' * B)
|
||||
endmodule
|
||||
module fulladder (A, B, CI, CO, Y);
|
||||
input A;
|
||||
input B;
|
||||
input CI;
|
||||
output CO;
|
||||
assign CO = (((A&B)|(B&CI))|(CI&A)); // (((A * B)+(B * CI))+(CI * A))
|
||||
output Y;
|
||||
assign Y = ((A^B)^CI); // ((A^B)^CI)
|
||||
endmodule
|
|
@ -0,0 +1,2 @@
|
|||
library(processdefs) {
|
||||
}
|
|
@ -2,9 +2,12 @@
|
|||
set -e
|
||||
|
||||
for x in *.lib; do
|
||||
echo "Running $x.."
|
||||
echo "read_verilog small.v" > test.ys
|
||||
echo "synth -top small" >> test.ys
|
||||
echo "dfflibmap -info -liberty ${x}" >> test.ys
|
||||
echo "Testing on $x.."
|
||||
echo "read_verilog small.v" > test.ys
|
||||
echo "synth -top small" >> test.ys
|
||||
echo "dfflibmap -info -liberty ${x}" >> test.ys
|
||||
../../yosys -ql ${x%.lib}.log -s test.ys
|
||||
../../yosys-filterlib - $x 2>/dev/null > $x.filtered
|
||||
../../yosys-filterlib -verilogsim $x > $x.verilogsim
|
||||
diff $x.filtered $x.filtered.ok && diff $x.verilogsim $x.verilogsim.ok
|
||||
done
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
library(supergate) {
|
||||
cell(DFF) {
|
||||
cell_footprint : dff ;
|
||||
area : 50 ;
|
||||
pin(D) {
|
||||
direction : input ;
|
||||
}
|
||||
pin(CK) {
|
||||
direction : input ;
|
||||
clock : true ;
|
||||
}
|
||||
ff(IQ, IQN) {
|
||||
clocked_on : CK ;
|
||||
next_state : D ;
|
||||
}
|
||||
pin(Q) {
|
||||
direction : output ;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
module DFF (D, CK, Q);
|
||||
reg IQ, IQN;
|
||||
input D;
|
||||
input CK;
|
||||
output Q;
|
||||
always @(posedge CK) begin
|
||||
// D
|
||||
IQ <= D;
|
||||
IQN <= ~(D);
|
||||
end
|
||||
endmodule
|
|
@ -0,0 +1,22 @@
|
|||
library(supergate) {
|
||||
cell(fulladder) {
|
||||
area : 8 ;
|
||||
pin(A) {
|
||||
direction : input ;
|
||||
}
|
||||
pin(B) {
|
||||
direction : input ;
|
||||
}
|
||||
pin(CI) {
|
||||
direction : input ;
|
||||
}
|
||||
pin(CO) {
|
||||
direction : output ;
|
||||
function : (((A * B)+(B * CI))+(CI * A)) ;
|
||||
}
|
||||
pin(Y) {
|
||||
direction : output ;
|
||||
function : ((A^B)^CI) ;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
module fulladder (A, B, CI, CO, Y);
|
||||
input A;
|
||||
input B;
|
||||
input CI;
|
||||
output CO;
|
||||
assign CO = (((A&B)|(B&CI))|(CI&A)); // (((A * B)+(B * CI))+(CI * A))
|
||||
output Y;
|
||||
assign Y = ((A^B)^CI); // ((A^B)^CI)
|
||||
endmodule
|
Loading…
Reference in New Issue