Refactor into AigerReader class

This commit is contained in:
Eddie Hung 2019-02-08 12:04:26 -08:00
parent 2a8cc36578
commit f1befe1b44
2 changed files with 94 additions and 81 deletions

View File

@ -30,25 +30,85 @@ YOSYS_NAMESPACE_BEGIN
#define log_debug log
static void parse_aiger_ascii(RTLIL::Module *module, std::istream &f, std::string clk_name);
static void parse_aiger_binary(RTLIL::Module *module, std::istream &f, std::string clk_name);
void parse_aiger(RTLIL::Design *design, std::istream &f, std::string clk_name)
AigerReader::AigerReader(RTLIL::Design *design, std::istream &f, std::string clk_name)
: design(design), f(f), clk_name(clk_name)
{
auto module = new RTLIL::Module;
module = new RTLIL::Module;
module->name = RTLIL::escape_id("aig"); // TODO: Name?
if (design->module(module->name))
log_error("Duplicate definition of module %s!\n", log_id(module->name));
}
void AigerReader::parse_aiger()
{
std::string header;
f >> header;
if (header == "aag")
parse_aiger_ascii(module, f, clk_name);
else if (header == "aig")
parse_aiger_binary(module, f, clk_name);
else
if (header != "aag" && header != "aig")
log_error("Unsupported AIGER file!\n");
// Parse rest of header
if (!(f >> M >> I >> L >> O >> A))
log_error("Invalid AIGER header\n");
// Optional values
B = C = J = F = 0;
for (auto &i : std::array<std::reference_wrapper<unsigned>,4>{B, C, J, F}) {
if (f.peek() != ' ') break;
if (!(f >> i))
log_error("Invalid AIGER header\n");
}
std::string line;
std::getline(f, line); // Ignore up to start of next line, as standard
// says anything that follows could be used for
// optional sections
log_debug("M=%u I=%u L=%u O=%u A=%u B=%u C=%u J=%u F=%u\n", M, I, L, O, A, B, C, J, F);
line_count = 1;
if (header == "aag")
parse_aiger_ascii();
else if (header == "aig")
parse_aiger_binary();
else
log_abort();
// Parse footer (symbol table, comments, etc.)
unsigned l1;
std::string s;
for (int c = f.peek(); c != EOF; c = f.peek(), ++line_count) {
if (c == 'i' || c == 'l' || c == 'o') {
f.ignore(1);
if (!(f >> l1 >> s))
log_error("Line %u cannot be interpreted as a symbol entry!\n", line_count);
if ((c == 'i' && l1 > inputs.size()) || (c == 'l' && l1 > latches.size()) || (c == 'o' && l1 > outputs.size()))
log_error("Line %u has invalid symbol position!\n", line_count);
RTLIL::Wire* wire;
if (c == 'i') wire = inputs[l1];
else if (c == 'l') wire = latches[l1];
else if (c == 'o') wire = outputs[l1];
else log_abort();
module->rename(wire, stringf("\\%s", s.c_str()));
}
else if (c == 'b' || c == 'j' || c == 'f') {
// TODO
}
else if (c == 'c') {
f.ignore(1);
if (f.peek() == '\n')
break;
// Else constraint (TODO)
break;
}
else
log_error("Line %u: cannot interpret first character '%c'!\n", line_count, c);
std::getline(f, line); // Ignore up to start of next line
}
module->fixup_ports();
design->add(module);
}
@ -81,38 +141,14 @@ static RTLIL::Wire* createWireIfNotExists(RTLIL::Module *module, unsigned litera
return wire;
}
static void parse_aiger_header(std::istream &f, unsigned &M, unsigned &I, unsigned &L, unsigned &O, unsigned &A, unsigned &B, unsigned &C, unsigned &J, unsigned &F)
void AigerReader::parse_aiger_ascii()
{
if (!(f >> M >> I >> L >> O >> A))
log_error("Invalid AIGER header\n");
for (auto &i : std::array<std::reference_wrapper<unsigned>,4>{B, C, J, F}) {
if (f.peek() != ' ') break;
if (!(f >> i))
log_error("Invalid AIGER header\n");
}
std::string line;
std::getline(f, line); // Ignore up to start of next line, as standard
// says anything that follows could be used for
// optional sections
log_debug("M=%u I=%u L=%u O=%u A=%u B=%u C=%u J=%u F=%u\n", M, I, L, O, A, B, C, J, F);
}
static void parse_aiger_ascii(RTLIL::Module *module, std::istream &f, std::string clk_name)
{
unsigned M, I, L, O, A;
unsigned B=0, C=0, J=0, F=0; // Optional in AIGER 1.9
parse_aiger_header(f, M, I, L, O, A, B, C, J, F);
unsigned line_count = 1;
std::string line;
std::stringstream ss;
unsigned l1, l2, l3;
// Parse inputs
std::vector<RTLIL::Wire*> inputs;
for (unsigned i = 0; i < I; ++i, ++line_count) {
if (!(f >> l1))
log_error("Line %u cannot be interpreted as an input!\n", line_count);
@ -124,7 +160,6 @@ static void parse_aiger_ascii(RTLIL::Module *module, std::istream &f, std::strin
}
// Parse latches
std::vector<RTLIL::Wire*> latches;
RTLIL::Wire *clk_wire = nullptr;
if (L > 0) {
RTLIL::IdString clk_id = RTLIL::escape_id(clk_name.c_str());
@ -165,7 +200,6 @@ static void parse_aiger_ascii(RTLIL::Module *module, std::istream &f, std::strin
}
// Parse outputs
std::vector<RTLIL::Wire*> outputs;
for (unsigned i = 0; i < O; ++i, ++line_count) {
if (!(f >> l1))
log_error("Line %u cannot be interpreted as an output!\n", line_count);
@ -210,39 +244,6 @@ static void parse_aiger_ascii(RTLIL::Module *module, std::istream &f, std::strin
and_cell->setPort("\\Y", o_wire);
}
std::getline(f, line); // Ignore up to start of next line
std::string s;
for (int c = f.peek(); c != EOF; c = f.peek(), ++line_count) {
if (c == 'i' || c == 'l' || c == 'o') {
f.ignore(1);
if (!(f >> l1 >> s))
log_error("Line %u cannot be interpreted as a symbol entry!\n", line_count);
if ((c == 'i' && l1 > inputs.size()) || (c == 'l' && l1 > latches.size()) || (c == 'o' && l1 > outputs.size()))
log_error("Line %u has invalid symbol position!\n", line_count);
RTLIL::Wire* wire;
if (c == 'i') wire = inputs[l1];
else if (c == 'l') wire = latches[l1];
else if (c == 'o') wire = outputs[l1];
else log_abort();
module->rename(wire, stringf("\\%s", s.c_str()));
}
else if (c == 'b' || c == 'j' || c == 'f') {
// TODO
}
else if (c == 'c') {
f.ignore(1);
if (f.peek() == '\n')
break;
// Else constraint (TODO)
break;
}
else
log_error("Line %u: cannot interpret first character '%c'!\n", line_count, c);
std::getline(f, line); // Ignore up to start of next line
}
}
static unsigned parse_next_delta_literal(std::istream &f, unsigned ref)
@ -254,18 +255,12 @@ static unsigned parse_next_delta_literal(std::istream &f, unsigned ref)
return ref - (x | (ch << (7 * i)));
}
static void parse_aiger_binary(RTLIL::Module *module, std::istream &f, std::string clk_name)
void AigerReader::parse_aiger_binary()
{
unsigned M, I, L, O, A;
unsigned B=0, C=0, J=0, F=0; // Optional in AIGER 1.9
parse_aiger_header(f, M, I, L, O, A, B, C, J, F);
unsigned line_count = 1;
unsigned l1, l2, l3;
std::string line;
// Parse inputs
std::vector<RTLIL::Wire*> inputs;
for (unsigned i = 1; i <= I; ++i) {
RTLIL::Wire *wire = createWireIfNotExists(module, i << 1);
wire->port_input = true;
@ -273,7 +268,6 @@ static void parse_aiger_binary(RTLIL::Module *module, std::istream &f, std::stri
}
// Parse latches
std::vector<RTLIL::Wire*> latches;
RTLIL::Wire *clk_wire = nullptr;
if (L > 0) {
RTLIL::IdString clk_id = RTLIL::escape_id(clk_name.c_str());
@ -314,7 +308,6 @@ static void parse_aiger_binary(RTLIL::Module *module, std::istream &f, std::stri
}
// Parse outputs
std::vector<RTLIL::Wire*> outputs;
for (unsigned i = 0; i < O; ++i, ++line_count) {
if (!(f >> l1))
log_error("Line %u cannot be interpreted as an output!\n", line_count);
@ -385,7 +378,8 @@ struct AigerFrontend : public Frontend {
}
extra_args(f, filename, args, argidx);
parse_aiger(design, *f);
AigerReader reader(design, *f);
reader.parse_aiger();
}
} AigerFrontend;

View File

@ -24,7 +24,26 @@
YOSYS_NAMESPACE_BEGIN
extern void parse_aiger(RTLIL::Design *design, std::istream &f, std::string clk_name="clk");
struct AigerReader
{
RTLIL::Design *design;
std::istream &f;
std::string clk_name;
RTLIL::Module *module;
unsigned M, I, L, O, A;
unsigned B, C, J, F; // Optional in AIGER 1.9
unsigned line_count;
std::vector<RTLIL::Wire*> inputs;
std::vector<RTLIL::Wire*> latches;
std::vector<RTLIL::Wire*> outputs;
AigerReader(RTLIL::Design *design, std::istream &f, std::string clk_name="clk");
void parse_aiger();
void parse_aiger_ascii();
void parse_aiger_binary();
};
YOSYS_NAMESPACE_END