Support for aliases defined with .names construct
This commit is contained in:
parent
4035a6cb46
commit
7d5338c9be
|
@ -105,6 +105,7 @@ namespace {
|
||||||
string name;
|
string name;
|
||||||
unordered_map<string, Net::Direction> pins;
|
unordered_map<string, Net::Direction> pins;
|
||||||
vector<subckt> subcircuits;
|
vector<subckt> subcircuits;
|
||||||
|
vector<pair<string, string> > aliases;
|
||||||
bool operator<(model const & o) const{ return name < o.name; }
|
bool operator<(model const & o) const{ return name < o.name; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -136,15 +137,36 @@ Cell * Blif::load ( string cellPath ) //, Cell *cell )
|
||||||
bool hasName;
|
bool hasName;
|
||||||
|
|
||||||
string line;
|
string line;
|
||||||
|
vector<string> current_names;
|
||||||
while(getline(ccell, line)){
|
while(getline(ccell, line)){
|
||||||
istringstream linestream(line);
|
istringstream linestream(line);
|
||||||
string before_comment;
|
string before_comment;
|
||||||
getline(linestream, before_comment, '#');
|
getline(linestream, before_comment, '#');
|
||||||
istringstream tokens(before_comment);
|
istringstream tokens(before_comment);
|
||||||
string token;
|
string token;
|
||||||
while(tokens>>token){
|
if(tokens >> token){
|
||||||
assert(not token.empty());
|
assert(not token.empty());
|
||||||
if(token[0] == '.'){
|
if(token[0] == '.'){
|
||||||
|
// Process finished .names statement
|
||||||
|
if(not current_names.empty()){
|
||||||
|
if( current_names.size() != 4
|
||||||
|
or current_names[2] != "1" or current_names[3] != "1"
|
||||||
|
){
|
||||||
|
ostringstream mess;
|
||||||
|
mess << "Name statement is not an alias and will be ignored "
|
||||||
|
<< "(map to standard cells for functions and tie cells for constants)\n";
|
||||||
|
for(string const & S: current_names){
|
||||||
|
mess << S << " ";
|
||||||
|
}
|
||||||
|
mess << "\n";
|
||||||
|
cerr << Warning(mess.str());
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
// Name statement is an alias: the second signal will map to the first
|
||||||
|
models.back().aliases.push_back(pair<string, string>(current_names[0], current_names[1]));
|
||||||
|
}
|
||||||
|
current_names.clear();
|
||||||
|
}
|
||||||
if(token == ".model"){
|
if(token == ".model"){
|
||||||
if(state != EXT)
|
if(state != EXT)
|
||||||
throw Error("Nested model are not supported\n");
|
throw Error("Nested model are not supported\n");
|
||||||
|
@ -162,13 +184,11 @@ Cell * Blif::load ( string cellPath ) //, Cell *cell )
|
||||||
models.back().subcircuits.push_back(subckt());
|
models.back().subcircuits.push_back(subckt());
|
||||||
}
|
}
|
||||||
else if(token == ".names"){
|
else if(token == ".names"){
|
||||||
cerr << Warning("BLIF names are ignored\n");
|
|
||||||
if(state == EXT)
|
if(state == EXT)
|
||||||
throw Error("Names without an enclosing model are not supported\n");
|
throw Error("Names without an enclosing model are not supported\n");
|
||||||
if(state == MODEL and not hasName)
|
if(state == MODEL and not hasName)
|
||||||
throw Error("Model has no name\n");
|
throw Error("Model has no name\n");
|
||||||
state = NAMES;
|
state = NAMES;
|
||||||
hasName = false;
|
|
||||||
}
|
}
|
||||||
else if(token == ".latch"){
|
else if(token == ".latch"){
|
||||||
throw Error("Latch constructs are not understood by the parser\n");
|
throw Error("Latch constructs are not understood by the parser\n");
|
||||||
|
@ -189,53 +209,68 @@ Cell * Blif::load ( string cellPath ) //, Cell *cell )
|
||||||
state = EXT;
|
state = EXT;
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
throw Error("Unexpected control token\n");
|
ostringstream mess;
|
||||||
|
mess << "Unknown control token <" << token << ">\n";
|
||||||
|
throw Error(mess.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else{ // Either a pin or an input/output definition
|
else if(state == NAMES){
|
||||||
if(state == INPUTS or state == OUTPUTS){
|
// Part of a cover for a logic function
|
||||||
auto it = models.back().pins.find(token);
|
current_names.push_back(token);
|
||||||
Net::Direction D = (state == INPUTS)? Net::Direction::DirIn : Net::Direction::DirOut;
|
}
|
||||||
if(it != models.back().pins.end()){
|
else{
|
||||||
it->second = static_cast<Net::Direction::Code>(D | it->second);
|
ostringstream mess;
|
||||||
}
|
mess << "Encountered a non-control token at the beginning of a line: <" << token << ">\n";
|
||||||
else{
|
throw Error(mess.str());
|
||||||
models.back().pins.insert(pair<string, Net::Direction>(token, D));
|
}
|
||||||
}
|
}
|
||||||
}
|
// Process all tokens after the control
|
||||||
else if(state == SUBCKT){
|
while(tokens >> token){
|
||||||
if(hasName){
|
assert(not token.empty());
|
||||||
// Encountered a pin: need to be processed
|
// Either a pin or an input/output definition
|
||||||
istringstream token_stream(token);
|
if(state == INPUTS or state == OUTPUTS){
|
||||||
string before_space, after_space;
|
auto it = models.back().pins.find(token);
|
||||||
getline(token_stream, before_space, '=');
|
Net::Direction D = (state == INPUTS)? Net::Direction::DirIn : Net::Direction::DirOut;
|
||||||
getline(token_stream, after_space, '=');
|
if(it != models.back().pins.end()){
|
||||||
if(token_stream){
|
it->second = static_cast<Net::Direction::Code>(D | it->second);
|
||||||
Error("Encountered more than one '=' in token");
|
|
||||||
}
|
|
||||||
models.back().subcircuits.back().pins.push_back(pair<string, string>(before_space, after_space));
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
models.back().subcircuits.back().cell = token;
|
|
||||||
hasName = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(state == NAMES){
|
|
||||||
// TODO; now just ignored
|
|
||||||
}
|
|
||||||
else if(state == MODEL){
|
|
||||||
if(hasName)
|
|
||||||
throw Error("Unexpected token after model name\n");
|
|
||||||
else{
|
|
||||||
models.back().name = token;
|
|
||||||
cmess2 << "Processing model <" << token << ">" << endl;
|
|
||||||
hasName = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
throw Error("Unexpected token\n");
|
models.back().pins.insert(pair<string, Net::Direction>(token, D));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if(state == SUBCKT){
|
||||||
|
if(hasName){
|
||||||
|
// Encountered a pin: need to be processed
|
||||||
|
istringstream token_stream(token);
|
||||||
|
string before_space, after_space;
|
||||||
|
getline(token_stream, before_space, '=');
|
||||||
|
getline(token_stream, after_space, '=');
|
||||||
|
if(token_stream){
|
||||||
|
Error("Encountered more than one '=' in token");
|
||||||
|
}
|
||||||
|
models.back().subcircuits.back().pins.push_back(pair<string, string>(before_space, after_space));
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
models.back().subcircuits.back().cell = token;
|
||||||
|
hasName = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(state == NAMES){
|
||||||
|
current_names.push_back(token);
|
||||||
|
}
|
||||||
|
else if(state == MODEL){
|
||||||
|
if(hasName)
|
||||||
|
throw Error("Unexpected token after model name\n");
|
||||||
|
else{
|
||||||
|
models.back().name = token;
|
||||||
|
cmess2 << "Processing model <" << token << ">" << endl;
|
||||||
|
hasName = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
throw Error("Unexpected token\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
line.clear();
|
line.clear();
|
||||||
}
|
}
|
||||||
|
@ -268,6 +303,10 @@ Cell * Blif::load ( string cellPath ) //, Cell *cell )
|
||||||
for(auto const & P : S.pins){
|
for(auto const & P : S.pins){
|
||||||
net_names.insert(P.second);
|
net_names.insert(P.second);
|
||||||
}
|
}
|
||||||
|
for(auto const & A : M.aliases){
|
||||||
|
net_names.insert(A.first);
|
||||||
|
net_names.insert(A.second);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for(auto const & P : M.pins){
|
for(auto const & P : M.pins){
|
||||||
net_names.insert(P.first);
|
net_names.insert(P.first);
|
||||||
|
@ -306,6 +345,9 @@ Cell * Blif::load ( string cellPath ) //, Cell *cell )
|
||||||
//connectSupplyNets(instance, design);
|
//connectSupplyNets(instance, design);
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
|
for(auto alias : M.aliases){
|
||||||
|
design->getNet( alias.first )->merge(design->getNet( alias.second ));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
cmess2 << "BLIF file loaded" << endl;
|
cmess2 << "BLIF file loaded" << endl;
|
||||||
if(model_cells.empty()){
|
if(model_cells.empty()){
|
||||||
|
|
Loading…
Reference in New Issue