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