get_ports bus range
Signed-off-by: James Cherry <cherry@parallaxsw.com>
This commit is contained in:
parent
3c70c9bee1
commit
7514224f6c
|
|
@ -82,8 +82,6 @@ public:
|
|||
const char *filename(const Cell *cell) override;
|
||||
Port *findPort(const Cell *cell,
|
||||
const char *name) const override;
|
||||
PortSeq findPortsMatching(const Cell *cell,
|
||||
const PatternMatch *pattern) const override;
|
||||
bool isLeaf(const Cell *cell) const override;
|
||||
CellPortIterator *portIterator(const Cell *cell) const override;
|
||||
CellPortBitIterator *portBitIterator(const Cell *cell) const override;
|
||||
|
|
|
|||
|
|
@ -148,7 +148,7 @@ public:
|
|||
virtual Port *findPort(const Cell *cell,
|
||||
const char *name) const = 0;
|
||||
virtual PortSeq findPortsMatching(const Cell *cell,
|
||||
const PatternMatch *pattern) const = 0;
|
||||
const PatternMatch *pattern) const;
|
||||
virtual bool isLeaf(const Cell *cell) const = 0;
|
||||
virtual CellPortIterator *portIterator(const Cell *cell) const = 0;
|
||||
// Iterate over port bits (expanded buses).
|
||||
|
|
|
|||
|
|
@ -60,27 +60,32 @@ parseBusName(const char *name,
|
|||
// bus_name is set to null if name is not a range.
|
||||
// Caller must delete returned bus_name string.
|
||||
void
|
||||
parseBusRange(const char *name,
|
||||
const char brkt_left,
|
||||
const char brkt_right,
|
||||
char escape,
|
||||
// Return values.
|
||||
bool &is_bus,
|
||||
string &bus_name,
|
||||
int &from,
|
||||
int &to);
|
||||
parseBusName(const char *name,
|
||||
const char brkt_left,
|
||||
const char brkt_right,
|
||||
char escape,
|
||||
// Return values.
|
||||
bool &is_bus,
|
||||
bool &is_range,
|
||||
string &bus_name,
|
||||
int &from,
|
||||
int &to,
|
||||
bool &subscript_wild);
|
||||
|
||||
// brkt_lefts and brkt_rights are corresponding strings of legal
|
||||
// bus brackets such as "[(<" and "])>".
|
||||
void
|
||||
parseBusRange(const char *name,
|
||||
const char *brkts_left,
|
||||
const char *brkts_right,
|
||||
const char escape,
|
||||
// Return values.
|
||||
bool &is_bus,
|
||||
string &bus_name,
|
||||
int &from,
|
||||
int &to);
|
||||
parseBusName(const char *name,
|
||||
const char *brkts_left,
|
||||
const char *brkts_right,
|
||||
const char escape,
|
||||
// Return values.
|
||||
bool &is_bus,
|
||||
bool &is_range,
|
||||
string &bus_name,
|
||||
int &from,
|
||||
int &to,
|
||||
bool &subscript_wild);
|
||||
|
||||
// Insert escapes before ch1 and ch2 in token.
|
||||
string
|
||||
|
|
|
|||
|
|
@ -5637,13 +5637,13 @@ PortNameBitIterator::init(const char *port_name)
|
|||
else {
|
||||
// Check for bus range.
|
||||
LibertyLibrary *library = visitor_->library();
|
||||
bool is_bus;
|
||||
bool is_bus, is_range, subscript_wild;
|
||||
string bus_name;
|
||||
int from, to;
|
||||
parseBusRange(port_name, library->busBrktLeft(),
|
||||
library->busBrktRight(), '\\',
|
||||
is_bus, bus_name, from, to);
|
||||
if (is_bus) {
|
||||
parseBusName(port_name, library->busBrktLeft(),
|
||||
library->busBrktRight(), '\\',
|
||||
is_bus, is_range, bus_name, from, to, subscript_wild);
|
||||
if (is_range) {
|
||||
port = visitor_->findPort(port_name);
|
||||
if (port) {
|
||||
if (port->isBus()) {
|
||||
|
|
|
|||
|
|
@ -275,32 +275,6 @@ ConcreteCell::portCount() const
|
|||
return ports_.size();
|
||||
}
|
||||
|
||||
PortSeq
|
||||
ConcreteCell::findPortsMatching(const PatternMatch *pattern) const
|
||||
{
|
||||
PortSeq matches;
|
||||
char bus_brkt_right = library_->busBrktRight();
|
||||
const char *pattern1 = pattern->pattern();
|
||||
bool bus_pattern = (pattern1[strlen(pattern1) - 1] == bus_brkt_right);
|
||||
ConcreteCellPortIterator *port_iter = portIterator();
|
||||
while (port_iter->hasNext()) {
|
||||
ConcretePort *port = port_iter->next();
|
||||
if (port->isBus() && bus_pattern) {
|
||||
ConcretePortMemberIterator *member_iter = port->memberIterator();
|
||||
while (member_iter->hasNext()) {
|
||||
ConcretePort *port_bit = member_iter->next();
|
||||
if (pattern->match(port_bit->name()))
|
||||
matches.push_back(reinterpret_cast<Port*>(port_bit));
|
||||
}
|
||||
delete member_iter;
|
||||
}
|
||||
else if (pattern->match(port->name()))
|
||||
matches.push_back(reinterpret_cast<Port*>(port));
|
||||
}
|
||||
delete port_iter;
|
||||
return matches;
|
||||
}
|
||||
|
||||
ConcreteCellPortIterator *
|
||||
ConcreteCell::portIterator() const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -605,14 +605,6 @@ ConcreteNetwork::findPort(const Cell *cell,
|
|||
return reinterpret_cast<Port*>(ccell->findPort(name));
|
||||
}
|
||||
|
||||
PortSeq
|
||||
ConcreteNetwork::findPortsMatching(const Cell *cell,
|
||||
const PatternMatch *pattern) const
|
||||
{
|
||||
const ConcreteCell *ccell = reinterpret_cast<const ConcreteCell*>(cell);
|
||||
return ccell->findPortsMatching(pattern);
|
||||
}
|
||||
|
||||
bool
|
||||
ConcreteNetwork::isLeaf(const Cell *cell) const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
#include "Liberty.hh"
|
||||
#include "PortDirection.hh"
|
||||
#include "Corner.hh"
|
||||
#include "ParseBus.hh"
|
||||
|
||||
namespace sta {
|
||||
|
||||
|
|
@ -56,6 +57,63 @@ Network::libertyLibrary(const Cell *cell) const
|
|||
return libertyCell(cell)->libertyLibrary();
|
||||
}
|
||||
|
||||
PortSeq
|
||||
Network::findPortsMatching(const Cell *cell,
|
||||
const PatternMatch *pattern) const
|
||||
{
|
||||
PortSeq matches;
|
||||
bool is_bus, is_range, subscript_wild;
|
||||
string bus_name;
|
||||
int from, to;
|
||||
parseBusName(pattern->pattern(), '[', ']', '\\',
|
||||
is_bus, is_range, bus_name, from, to, subscript_wild);
|
||||
if (is_bus) {
|
||||
PatternMatch bus_pattern(bus_name.c_str(), pattern);
|
||||
CellPortIterator *port_iter = portIterator(cell);
|
||||
while (port_iter->hasNext()) {
|
||||
Port *port = port_iter->next();
|
||||
if (isBus(port)
|
||||
&& bus_pattern.match(name(port))) {
|
||||
if (is_range) {
|
||||
// bus[8:0]
|
||||
if (from > to)
|
||||
std::swap(from, to);
|
||||
for (int bit = from; bit <= to; bit++) {
|
||||
Port *port_bit = findBusBit(port, bit);
|
||||
matches.push_back(port_bit);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (subscript_wild) {
|
||||
PortMemberIterator *member_iter = memberIterator(port);
|
||||
while (member_iter->hasNext()) {
|
||||
Port *port_bit = member_iter->next();
|
||||
matches.push_back(port_bit);
|
||||
}
|
||||
delete member_iter;
|
||||
}
|
||||
else {
|
||||
// bus[0]
|
||||
Port *port_bit = findBusBit(port, from);
|
||||
matches.push_back(port_bit);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
delete port_iter;
|
||||
}
|
||||
else {
|
||||
CellPortIterator *port_iter = portIterator(cell);
|
||||
while (port_iter->hasNext()) {
|
||||
Port *port = port_iter->next();
|
||||
if (pattern->match(name(port)))
|
||||
matches.push_back(port);
|
||||
}
|
||||
delete port_iter;
|
||||
}
|
||||
return matches;
|
||||
}
|
||||
|
||||
LibertyLibrary *
|
||||
Network::libertyLibrary(const Instance *instance) const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -95,37 +95,43 @@ parseBusName(const char *name,
|
|||
}
|
||||
|
||||
void
|
||||
parseBusRange(const char *name,
|
||||
const char brkt_left,
|
||||
const char brkt_right,
|
||||
char escape,
|
||||
// Return values.
|
||||
bool &is_bus,
|
||||
string &bus_name,
|
||||
int &from,
|
||||
int &to)
|
||||
parseBusName(const char *name,
|
||||
const char brkt_left,
|
||||
const char brkt_right,
|
||||
char escape,
|
||||
// Return values.
|
||||
bool &is_bus,
|
||||
bool &is_range,
|
||||
string &bus_name,
|
||||
int &from,
|
||||
int &to,
|
||||
bool &subscript_wild)
|
||||
{
|
||||
const char brkts_left[2] = {brkt_left, '\0'};
|
||||
const char brkts_right[2] = {brkt_right, '\0'};
|
||||
parseBusRange(name, brkts_left, brkts_right, escape,
|
||||
is_bus, bus_name, from, to);
|
||||
parseBusName(name, brkts_left, brkts_right, escape,
|
||||
is_bus, is_range, bus_name, from, to, subscript_wild);
|
||||
}
|
||||
|
||||
void
|
||||
parseBusRange(const char *name,
|
||||
const char *brkts_left,
|
||||
const char *brkts_right,
|
||||
char escape,
|
||||
// Return values.
|
||||
bool &is_bus,
|
||||
string &bus_name,
|
||||
int &from,
|
||||
int &to)
|
||||
parseBusName(const char *name,
|
||||
const char *brkts_left,
|
||||
const char *brkts_right,
|
||||
char escape,
|
||||
// Return values.
|
||||
bool &is_bus,
|
||||
bool &is_range,
|
||||
string &bus_name,
|
||||
int &from,
|
||||
int &to,
|
||||
bool &subscript_wild)
|
||||
{
|
||||
is_bus = false;
|
||||
is_range = false;
|
||||
subscript_wild = false;
|
||||
size_t len = strlen(name);
|
||||
// Shortest bus range is a[1:0].
|
||||
if (len >= 6
|
||||
// Shortest bus is a[0].
|
||||
if (len >= 4
|
||||
// Escaped bus brackets are not buses.
|
||||
&& name[len - 2] != escape) {
|
||||
char last_ch = name[len - 1];
|
||||
|
|
@ -135,17 +141,25 @@ parseBusRange(const char *name,
|
|||
char brkt_left = brkts_left[brkt_index];
|
||||
const char *left = strrchr(name, brkt_left);
|
||||
if (left) {
|
||||
is_bus = true;
|
||||
// Check for bus range.
|
||||
const char range_sep = ':';
|
||||
const char *range = strchr(name, range_sep);
|
||||
if (range) {
|
||||
is_bus = true;
|
||||
is_range = true;
|
||||
bus_name.append(name, left - name);
|
||||
// No need to terminate bus subscript because atoi stops
|
||||
// scanning at first non-digit character.
|
||||
from = atoi(left + 1);
|
||||
to = atoi(range + 1);
|
||||
}
|
||||
else {
|
||||
bus_name.append(name, left - name);
|
||||
if (left[1] == '*')
|
||||
subscript_wild = true;
|
||||
else
|
||||
from = to = atoi(left + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -135,11 +135,11 @@ ReadVcdActivities::setVarActivity(VcdVar *var,
|
|||
if (var->width() == 1)
|
||||
setVarActivity(sta_name.c_str(), var_values, 0);
|
||||
else {
|
||||
bool is_bus;
|
||||
bool is_bus, is_range, subscript_wild;
|
||||
string bus_name;
|
||||
int from, to;
|
||||
parseBusRange(sta_name.c_str(), '[', ']', '\\',
|
||||
is_bus, bus_name, from, to);
|
||||
parseBusName(sta_name.c_str(), '[', ']', '\\',
|
||||
is_bus, is_range, bus_name, from, to, subscript_wild);
|
||||
int value_bit = 0;
|
||||
if (to < from) {
|
||||
for (int bus_bit = to; bus_bit <= from; bus_bit++) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue