2018-09-28 17:54:21 +02:00
|
|
|
// OpenSTA, Static Timing Analyzer
|
2020-03-07 03:50:37 +01:00
|
|
|
// Copyright (c) 2020, Parallax Software, Inc.
|
2018-09-28 17:54:21 +02:00
|
|
|
//
|
|
|
|
|
// This program is free software: you can redistribute it and/or modify
|
|
|
|
|
// it under the terms of the GNU General Public License as published by
|
|
|
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
|
|
|
// (at your option) any later version.
|
|
|
|
|
//
|
|
|
|
|
// This program is distributed in the hope that it will be useful,
|
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
// GNU General Public License for more details.
|
|
|
|
|
//
|
|
|
|
|
// You should have received a copy of the GNU General Public License
|
|
|
|
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
|
|
2020-04-05 20:35:51 +02:00
|
|
|
#include "network/VerilogNamespace.hh"
|
|
|
|
|
|
2018-09-28 17:54:21 +02:00
|
|
|
#include <ctype.h>
|
2020-04-05 20:35:51 +02:00
|
|
|
|
|
|
|
|
#include "util/StringUtil.hh"
|
|
|
|
|
#include "network/ParseBus.hh"
|
2018-09-28 17:54:21 +02:00
|
|
|
|
|
|
|
|
namespace sta {
|
|
|
|
|
|
|
|
|
|
const char *
|
|
|
|
|
instanceVerilogName(const char *sta_name,
|
|
|
|
|
const char escape)
|
|
|
|
|
{
|
2019-07-04 06:18:38 +02:00
|
|
|
return staToVerilog(sta_name, escape);
|
2018-09-28 17:54:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const char *
|
|
|
|
|
netVerilogName(const char *sta_name,
|
|
|
|
|
const char escape)
|
|
|
|
|
{
|
2019-07-04 06:18:38 +02:00
|
|
|
char *bus_name;
|
|
|
|
|
int index;
|
2019-08-14 06:34:35 +02:00
|
|
|
parseBusName(sta_name, '[', ']', escape, bus_name, index);
|
2019-08-13 07:56:32 +02:00
|
|
|
if (bus_name) {
|
|
|
|
|
const char *vname = stringPrintTmp("%s[%d]",
|
|
|
|
|
staToVerilog(bus_name, escape),
|
|
|
|
|
index);
|
|
|
|
|
stringDelete(bus_name);
|
|
|
|
|
return vname;
|
|
|
|
|
}
|
2019-07-04 06:18:38 +02:00
|
|
|
else
|
|
|
|
|
return staToVerilog(sta_name, escape);
|
2018-09-28 17:54:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const char *
|
|
|
|
|
portVerilogName(const char *sta_name,
|
|
|
|
|
const char escape)
|
|
|
|
|
{
|
2019-07-04 06:18:38 +02:00
|
|
|
return staToVerilog(sta_name, escape);
|
2018-09-28 17:54:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Append ch to str at insert. Resize str if necessary.
|
|
|
|
|
static inline void
|
|
|
|
|
vstringAppend(char *&str,
|
|
|
|
|
char *&str_end,
|
|
|
|
|
char *&insert,
|
|
|
|
|
char ch)
|
|
|
|
|
{
|
|
|
|
|
if (insert == str_end) {
|
|
|
|
|
size_t length = str_end - str;
|
|
|
|
|
size_t length2 = length * 2;
|
|
|
|
|
char *new_str = makeTmpString(length2);
|
|
|
|
|
strncpy(new_str, str, length);
|
|
|
|
|
str = new_str;
|
|
|
|
|
str_end = &str[length2];
|
|
|
|
|
insert = &str[length];
|
|
|
|
|
}
|
|
|
|
|
*insert++ = ch;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const char *
|
|
|
|
|
staToVerilog(const char *sta_name,
|
|
|
|
|
const char escape)
|
|
|
|
|
{
|
|
|
|
|
const char bus_brkt_left = '[';
|
|
|
|
|
const char bus_brkt_right = ']';
|
|
|
|
|
// Leave room for leading escape and trailing space if the name
|
|
|
|
|
// needs to be escaped.
|
|
|
|
|
size_t verilog_name_length = strlen(sta_name) + 3;
|
|
|
|
|
char *verilog_name = makeTmpString(verilog_name_length);
|
|
|
|
|
char *verilog_name_end = &verilog_name[verilog_name_length];
|
|
|
|
|
char *v = verilog_name;
|
|
|
|
|
// Assume the name has to be escaped and start copying while scanning.
|
|
|
|
|
bool escaped = false;
|
|
|
|
|
*v++ = '\\';
|
|
|
|
|
for (const char *s = sta_name; *s ; s++) {
|
|
|
|
|
char ch = s[0];
|
|
|
|
|
if (ch == escape) {
|
|
|
|
|
char next_ch = s[1];
|
|
|
|
|
if (next_ch == escape) {
|
|
|
|
|
vstringAppend(verilog_name, verilog_name_end, v, ch);
|
|
|
|
|
vstringAppend(verilog_name, verilog_name_end, v, next_ch);
|
|
|
|
|
s++;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
// Skip escape.
|
|
|
|
|
escaped = true;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
bool is_brkt = (ch == bus_brkt_left || ch == bus_brkt_right);
|
|
|
|
|
if ((!(isalnum(ch) || ch == '_') && !is_brkt)
|
2019-07-04 06:18:38 +02:00
|
|
|
|| is_brkt)
|
2018-09-28 17:54:21 +02:00
|
|
|
escaped = true;
|
|
|
|
|
vstringAppend(verilog_name, verilog_name_end, v, ch);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (escaped) {
|
|
|
|
|
// Add a terminating space.
|
|
|
|
|
vstringAppend(verilog_name, verilog_name_end, v, ' ');
|
|
|
|
|
vstringAppend(verilog_name, verilog_name_end, v, '\0');
|
|
|
|
|
return verilog_name;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
return sta_name;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const char *
|
|
|
|
|
verilogToSta(const char *verilog_name)
|
|
|
|
|
{
|
|
|
|
|
if (verilog_name[0] == '\\') {
|
|
|
|
|
const char divider = '/';
|
|
|
|
|
const char escape = '\\';
|
|
|
|
|
const char bus_brkt_left = '[';
|
|
|
|
|
const char bus_brkt_right = ']';
|
|
|
|
|
size_t sta_name_length = strlen(verilog_name) + 1;
|
|
|
|
|
char *sta_name = makeTmpString(sta_name_length);
|
|
|
|
|
char *sta_name_end = &sta_name[sta_name_length];
|
|
|
|
|
char *s = sta_name;
|
|
|
|
|
for (const char *v = &verilog_name[1]; *v ; v++) {
|
|
|
|
|
char ch = *v;
|
|
|
|
|
if (ch == divider
|
|
|
|
|
|| ch == bus_brkt_left
|
|
|
|
|
|| ch == bus_brkt_right
|
|
|
|
|
|| ch == escape)
|
|
|
|
|
// Escape dividers, bus brackets and escapes.
|
|
|
|
|
vstringAppend(sta_name, sta_name_end, s, escape);
|
|
|
|
|
vstringAppend(sta_name, sta_name_end, s, ch);
|
|
|
|
|
// Don't include the last character, which is always a space.
|
|
|
|
|
if (v[2] == '\0')
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
vstringAppend(sta_name, sta_name_end, s, '\0');
|
|
|
|
|
return sta_name;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
return verilog_name;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace
|