Files
OpenDB/src/db/dbWireCodec.cpp
Matt Liberty b4b41644eb Fully support RECT in DEF net routing
The wire encoder/decode now has a WOP_RECT opcode to store these shapes.
They are exposed in the decoder & dbWireShapeItr but not in the
higher level dbRtTree dbWireGraph classes.
2020-03-30 13:32:47 -07:00

1365 lines
34 KiB
C++

///////////////////////////////////////////////////////////////////////////////
// BSD 3-Clause License
//
// Copyright (c) 2019, Nefelus Inc
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * Neither the name of the copyright holder nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
#include <ctype.h>
#include "db.h"
#include "dbBlock.h"
#include "dbNet.h"
#include "dbTable.h"
#include "dbTech.h"
#include "dbTechLayerRule.h"
#include "dbWire.h"
#include "dbWireCodec.h"
#include "dbWireOpcode.h"
#include "logger.h"
namespace odb {
//////////////////////////////////////////////////////////////////////////////////
//
// dbWireEncoder
//
//////////////////////////////////////////////////////////////////////////////////
#define DB_WIRE_ENCODER_INVALID_VIA_LAYER 0
inline unsigned char dbWireEncoder::getOp(int idx)
{
return _opcodes[idx];
}
inline void dbWireEncoder::updateOp(int idx, unsigned char op)
{
_opcodes[idx] = op;
}
inline void dbWireEncoder::addOp(unsigned char op, int value)
{
_data.push_back(value);
_opcodes.push_back(op);
++_idx;
}
inline unsigned char dbWireEncoder::getWireType(dbWireType type)
{
unsigned char wire_type = 0;
switch (type.getValue()) {
case dbWireType::NONE:
wire_type = WOP_NONE;
break;
case dbWireType::COVER:
wire_type = WOP_COVER;
break;
case dbWireType::FIXED:
wire_type = WOP_FIXED;
break;
case dbWireType::ROUTED:
wire_type = WOP_ROUTED;
break;
case dbWireType::NOSHIELD:
wire_type = WOP_NOSHIELD;
break;
default:
_wire_type = WOP_NONE;
break;
}
return wire_type;
}
inline void dbWireEncoder::initPath(dbTechLayer* layer, dbWireType type)
{
initPath(layer, getWireType(type));
}
inline void dbWireEncoder::initPath(dbTechLayer* layer,
dbWireType type,
dbTechLayerRule* rule)
{
initPath(layer, getWireType(type), rule);
}
void dbWireEncoder::initPath(dbTechLayer* layer, unsigned char wire_type)
{
_wire_type = wire_type;
_point_cnt = 0;
_via_cnt = 0;
_layer = layer;
_non_default_rule = 0;
_rule_opcode = 0;
_prev_extended_colinear_pnt = false;
}
void dbWireEncoder::initPath(dbTechLayer* layer,
unsigned char wire_type,
dbTechLayerRule* rule)
{
_wire_type = wire_type;
_point_cnt = 0;
_via_cnt = 0;
_layer = layer;
_non_default_rule = rule->getImpl()->getOID();
if (rule->isBlockRule())
_rule_opcode = WOP_RULE | WOP_BLOCK_RULE;
else
_rule_opcode = WOP_RULE;
_prev_extended_colinear_pnt = false;
_x = 0;
_y = 0;
}
dbWireEncoder::dbWireEncoder()
{
_wire = NULL;
}
dbWireEncoder::~dbWireEncoder()
{
}
void dbWireEncoder::begin(dbWire* wire)
{
clear();
_wire = (_dbWire*) wire;
_block = wire->getBlock();
_tech = _block->getDb()->getTech();
}
void dbWireEncoder::clear()
{
_wire = NULL;
_block = NULL;
_tech = NULL;
_data.clear();
_opcodes.clear();
_layer = NULL;
_idx = 0;
_x = 0;
_y = 0;
_non_default_rule = 0;
_rule_opcode = 0;
_point_cnt = 0;
_via_cnt = 0;
_prev_extended_colinear_pnt = false;
}
void dbWireEncoder::append(dbWire* wire)
{
_wire = (_dbWire*) wire;
_block = wire->getBlock();
_tech = _block->getDb()->getTech();
_data = _wire->_data;
_opcodes = _wire->_opcodes;
_layer = NULL;
_idx = _data.size();
_x = 0;
_y = 0;
_non_default_rule = 0;
_rule_opcode = 0;
_point_cnt = 0;
_via_cnt = 0;
_prev_extended_colinear_pnt = false;
}
#define DB_WIRE_ENCODER_NON_ORTHOGANAL_SEGMENT 0
int dbWireEncoder::addPoint(int x, int y, uint property)
{
int jct_id = _idx;
if (_non_default_rule == 0) {
if (_point_cnt == 0) {
addOp(WOP_X | WOP_DEFAULT_WIDTH, x);
addOp(WOP_Y | WOP_DEFAULT_WIDTH, y);
_x = x;
_y = y;
jct_id++;
_point_cnt++;
} else if ((_x == x) && (_y == y)) {
addOp(WOP_COLINEAR | WOP_DEFAULT_WIDTH, 0);
} else if (_y == y) {
addOp(WOP_X | WOP_DEFAULT_WIDTH, x);
_x = x;
_point_cnt++;
} else if (_x == x) {
addOp(WOP_Y | WOP_DEFAULT_WIDTH, y);
_y = y;
_point_cnt++;
} else {
ZASSERT(DB_WIRE_ENCODER_NON_ORTHOGANAL_SEGMENT);
}
} else {
if (_point_cnt == 0) {
addOp(WOP_X, x);
addOp(WOP_Y, y);
_x = x;
_y = y;
_point_cnt++;
jct_id++;
} else if ((_x == x) && (_y == y)) {
addOp(WOP_COLINEAR, 0);
} else if (_y == y) {
addOp(WOP_X, x);
_x = x;
_point_cnt++;
} else if (_x == x) {
addOp(WOP_Y, y);
_y = y;
_point_cnt++;
} else {
ZASSERT(DB_WIRE_ENCODER_NON_ORTHOGANAL_SEGMENT);
}
if (_point_cnt
&& ((_point_cnt & (WOP_NON_DEFAULT_WIDTH_POINT_CNT - 1)) == 0))
addOp(_rule_opcode, _non_default_rule);
}
if (_point_cnt != 1)
addOp(WOP_PROPERTY, property);
_prev_extended_colinear_pnt = false;
return jct_id;
}
#define DB_WIRE_ENCODER_COLINEAR_EXT_RULE_1() \
((_point_cnt > 1) || ((_point_cnt > 0) && (_via_cnt > 0)))
#define DB_WIRE_ENCODER_COLINEAR_EXT_RULE_2() \
(_prev_extended_colinear_pnt == false)
int dbWireEncoder::addPoint(int x, int y, int ext, uint property)
{
int jct_id = _idx;
if (_non_default_rule == 0) {
if (_point_cnt == 0) {
addOp(WOP_X | WOP_DEFAULT_WIDTH, x);
addOp(WOP_Y | WOP_EXTENSION | WOP_DEFAULT_WIDTH, y);
addOp(WOP_OPERAND, ext);
_x = x;
_y = y;
_point_cnt++;
jct_id++;
_prev_extended_colinear_pnt = false;
} else if ((_x == x) && (_y == y)) {
ZASSERT(DB_WIRE_ENCODER_COLINEAR_EXT_RULE_1());
ZASSERT(DB_WIRE_ENCODER_COLINEAR_EXT_RULE_2());
addOp(WOP_COLINEAR | WOP_EXTENSION | WOP_DEFAULT_WIDTH, ext);
_prev_extended_colinear_pnt = true;
} else if (_y == y) {
addOp(WOP_X | WOP_EXTENSION | WOP_DEFAULT_WIDTH, x);
addOp(WOP_OPERAND, ext);
_x = x;
_point_cnt++;
_prev_extended_colinear_pnt = false;
} else if (_x == x) {
addOp(WOP_Y | WOP_EXTENSION | WOP_DEFAULT_WIDTH, y);
addOp(WOP_OPERAND, ext);
_y = y;
_point_cnt++;
_prev_extended_colinear_pnt = false;
} else {
ZASSERT(DB_WIRE_ENCODER_NON_ORTHOGANAL_SEGMENT);
}
} else {
if (_point_cnt == 0) {
addOp(WOP_X, x);
addOp(WOP_Y | WOP_EXTENSION, y);
addOp(WOP_OPERAND, ext);
_x = x;
_y = y;
_point_cnt++;
jct_id++;
_prev_extended_colinear_pnt = false;
} else if ((_x == x) && (_y == y)) {
ZASSERT(DB_WIRE_ENCODER_COLINEAR_EXT_RULE_1());
ZASSERT(DB_WIRE_ENCODER_COLINEAR_EXT_RULE_2());
addOp(WOP_COLINEAR | WOP_EXTENSION, ext);
_prev_extended_colinear_pnt = true;
} else if (_y == y) {
addOp(WOP_X | WOP_EXTENSION, x);
addOp(WOP_OPERAND, ext);
_x = x;
_point_cnt++;
_prev_extended_colinear_pnt = false;
} else if (_x == x) {
addOp(WOP_Y | WOP_EXTENSION, y);
addOp(WOP_OPERAND, ext);
_y = y;
_point_cnt++;
_prev_extended_colinear_pnt = false;
} else {
ZASSERT(DB_WIRE_ENCODER_NON_ORTHOGANAL_SEGMENT);
}
if (_point_cnt
&& ((_point_cnt & (WOP_NON_DEFAULT_WIDTH_POINT_CNT - 1)) == 0))
addOp(_rule_opcode, _non_default_rule);
}
if (_point_cnt != 1)
addOp(WOP_PROPERTY, property);
return jct_id;
}
int dbWireEncoder::addVia(dbVia* via)
{
int jct_id = _idx;
ZASSERT(_point_cnt != 0);
dbTechLayer* top = via->getTopLayer();
dbTechLayer* bot = via->getBottomLayer();
if (top == _layer) {
_layer = bot;
addOp(WOP_VIA, via->getImpl()->getOID());
} else if (bot == _layer) {
_layer = top;
addOp(WOP_VIA | WOP_VIA_EXIT_TOP, via->getImpl()->getOID());
} else {
ZASSERT(DB_WIRE_ENCODER_INVALID_VIA_LAYER);
addOp(WOP_VIA, 0);
}
_via_cnt++;
return jct_id;
}
int dbWireEncoder::addTechVia(dbTechVia* via)
{
int jct_id = _idx;
ZASSERT(_point_cnt != 0);
dbTechLayer* top = via->getTopLayer();
dbTechLayer* bot = via->getBottomLayer();
if (top == _layer) {
_layer = bot;
addOp(WOP_TECH_VIA, via->getImpl()->getOID());
} else if (bot == _layer) {
_layer = top;
addOp(WOP_TECH_VIA | WOP_VIA_EXIT_TOP, via->getImpl()->getOID());
} else {
ZASSERT(DB_WIRE_ENCODER_INVALID_VIA_LAYER);
addOp(WOP_TECH_VIA, 0);
}
_via_cnt++;
return jct_id;
}
void dbWireEncoder::addRect(int deltaX1, int deltaY1, int deltaX2, int deltaY2)
{
// order must match dbWireDecoder::next
ZASSERT(_point_cnt != 0);
addOp(WOP_RECT, deltaX1);
addOp(WOP_OPERAND, deltaY1);
addOp(WOP_OPERAND, deltaX2);
addOp(WOP_OPERAND, deltaY2);
}
void dbWireEncoder::addITerm(dbITerm* iterm)
{
ZASSERT(_point_cnt != 0);
addOp(WOP_ITERM, iterm->getImpl()->getOID());
}
void dbWireEncoder::addBTerm(dbBTerm* bterm)
{
ZASSERT(_point_cnt != 0);
addOp(WOP_BTERM, bterm->getImpl()->getOID());
}
void dbWireEncoder::newPath(dbTechLayer* layer, dbWireType type)
{
initPath(layer, type);
addOp(WOP_PATH | _wire_type, layer->getImpl()->getOID());
}
void dbWireEncoder::newPath(dbTechLayer* layer,
dbWireType type,
dbTechLayerRule* rule)
{
initPath(layer, type, rule);
addOp(WOP_PATH | _wire_type, layer->getImpl()->getOID());
addOp(_rule_opcode, _non_default_rule);
}
void dbWireEncoder::newPath(int jct_id)
{
ZASSERT((jct_id >= 0) && (jct_id < _idx));
WirePoint pnt;
getPrevPoint(_tech, _block, _opcodes, _data, jct_id, true, pnt);
initPath(pnt._layer, _wire_type);
_x = pnt._x;
_y = pnt._y;
_point_cnt = 1;
addOp(WOP_JUNCTION | _wire_type, jct_id);
addOp(WOP_COLINEAR | WOP_DEFAULT_WIDTH, 0);
}
void dbWireEncoder::newPath(int jct_id, dbWireType type)
{
ZASSERT((jct_id >= 0) && (jct_id < _idx));
WirePoint pnt;
getPrevPoint(_tech, _block, _opcodes, _data, jct_id, true, pnt);
initPath(pnt._layer, type);
_x = pnt._x;
_y = pnt._y;
_point_cnt = 1;
addOp(WOP_JUNCTION | _wire_type, jct_id);
addOp(WOP_COLINEAR | WOP_DEFAULT_WIDTH, 0);
}
void dbWireEncoder::newPathShort(int jct_id,
dbTechLayer* layer,
dbWireType type)
{
ZASSERT((jct_id >= 0) && (jct_id < _idx));
initPath(layer, type);
addOp(WOP_SHORT | _wire_type, layer->getImpl()->getOID());
addOp(WOP_OPERAND, jct_id);
}
void dbWireEncoder::newPathVirtualWire(int jct_id,
dbTechLayer* layer,
dbWireType type)
{
ZASSERT((jct_id >= 0) && (jct_id < _idx));
initPath(layer, type);
addOp(WOP_VWIRE | _wire_type, layer->getImpl()->getOID());
addOp(WOP_OPERAND, jct_id);
}
void dbWireEncoder::newPathExt(int jct_id, int ext)
{
ZASSERT((jct_id >= 0) && (jct_id < _idx));
WirePoint pnt;
getPrevPoint(_tech, _block, _opcodes, _data, jct_id, true, pnt);
initPath(pnt._layer, _wire_type);
_x = pnt._x;
_y = pnt._y;
_point_cnt = 1;
addOp(WOP_JUNCTION | _wire_type, jct_id);
addOp(WOP_COLINEAR | WOP_EXTENSION | WOP_DEFAULT_WIDTH, ext);
}
void dbWireEncoder::newPathExt(int jct_id, int ext, dbWireType type)
{
ZASSERT((jct_id >= 0) && (jct_id < _idx));
WirePoint pnt;
getPrevPoint(_tech, _block, _opcodes, _data, jct_id, true, pnt);
initPath(pnt._layer, type);
_x = pnt._x;
_y = pnt._y;
_point_cnt = 1;
addOp(WOP_JUNCTION | _wire_type, jct_id);
addOp(WOP_COLINEAR | WOP_EXTENSION | WOP_DEFAULT_WIDTH, ext);
}
void dbWireEncoder::newPath(int jct_id, dbTechLayerRule* rule)
{
ZASSERT((jct_id >= 0) && (jct_id < _idx));
WirePoint pnt;
getPrevPoint(_tech, _block, _opcodes, _data, jct_id, true, pnt);
initPath(pnt._layer, _wire_type, rule);
_x = pnt._x;
_y = pnt._y;
_point_cnt = 1;
addOp(WOP_JUNCTION | _wire_type, jct_id);
addOp(_rule_opcode, _non_default_rule);
addOp(WOP_COLINEAR, 0);
}
void dbWireEncoder::newPath(int jct_id, dbWireType type, dbTechLayerRule* rule)
{
ZASSERT((jct_id >= 0) && (jct_id < _idx));
WirePoint pnt;
getPrevPoint(_tech, _block, _opcodes, _data, jct_id, true, pnt);
initPath(pnt._layer, type, rule);
_x = pnt._x;
_y = pnt._y;
_point_cnt = 1;
addOp(WOP_JUNCTION | _wire_type, jct_id);
addOp(_rule_opcode, _non_default_rule);
addOp(WOP_COLINEAR, 0);
}
void dbWireEncoder::newPathShort(int jct_id,
dbTechLayer* layer,
dbWireType type,
dbTechLayerRule* rule)
{
ZASSERT((jct_id >= 0) && (jct_id < _idx));
initPath(layer, type, rule);
addOp(WOP_SHORT | _wire_type, layer->getImpl()->getOID());
addOp(WOP_OPERAND, jct_id);
addOp(_rule_opcode, _non_default_rule);
}
void dbWireEncoder::newPathVirtualWire(int jct_id,
dbTechLayer* layer,
dbWireType type,
dbTechLayerRule* rule)
{
ZASSERT((jct_id >= 0) && (jct_id < _idx));
initPath(layer, type, rule);
addOp(WOP_VWIRE | _wire_type, layer->getImpl()->getOID());
addOp(WOP_OPERAND, jct_id);
addOp(_rule_opcode, _non_default_rule);
}
void dbWireEncoder::newPathExt(int jct_id, int ext, dbTechLayerRule* rule)
{
ZASSERT((jct_id >= 0) && (jct_id < _idx));
WirePoint pnt;
getPrevPoint(_tech, _block, _opcodes, _data, jct_id, true, pnt);
initPath(pnt._layer, _wire_type, rule);
_x = pnt._x;
_y = pnt._y;
_point_cnt = 1;
addOp(WOP_JUNCTION | _wire_type, jct_id);
addOp(_rule_opcode, _non_default_rule);
addOp(WOP_COLINEAR | WOP_EXTENSION, ext);
}
void dbWireEncoder::newPathExt(int jct_id,
int ext,
dbWireType type,
dbTechLayerRule* rule)
{
ZASSERT((jct_id >= 0) && (jct_id < _idx));
WirePoint pnt;
getPrevPoint(_tech, _block, _opcodes, _data, jct_id, true, pnt);
initPath(pnt._layer, type, rule);
_x = pnt._x;
_y = pnt._y;
_point_cnt = 1;
addOp(WOP_JUNCTION | _wire_type, jct_id);
addOp(_rule_opcode, _non_default_rule);
addOp(WOP_COLINEAR | WOP_EXTENSION, ext);
}
void dbWireEncoder::end()
{
if (_opcodes.size() == 0)
return;
uint n = _opcodes.size();
// Free the old memory
_wire->_data.~dbVector<int>();
new (&_wire->_data) dbVector<int>();
_wire->_data.reserve(n);
_wire->_data = _data;
// Free the old memory
_wire->_opcodes.~dbVector<unsigned char>();
new (&_wire->_opcodes) dbVector<unsigned char>();
_wire->_opcodes.reserve(n);
_wire->_opcodes = _opcodes;
// Should we calculate the bbox???
((_dbBlock*) _block)->_flags._valid_bbox = 0;
_point_cnt = 0;
}
//////////////////////////////////////////////////////////////////////////////////
//
// dbWireDecoder
//
//////////////////////////////////////////////////////////////////////////////////
#define DB_WIRE_DECODE_INVALID_OPCODE 0
#define DB_WIRE_DECODE_INVALID_OPCODE_SEQUENCE 0
#define DB_WIRE_DECODE_INVALID_VIA_LAYER 0
dbWireDecoder::dbWireDecoder()
{
_wire = NULL;
_block = NULL;
_tech = NULL;
}
dbWireDecoder::~dbWireDecoder()
{
}
void dbWireDecoder::begin(dbWire* wire)
{
_wire = (_dbWire*) wire;
_block = wire->getBlock();
_tech = _block->getDb()->getTech();
_x = 0;
_y = 0;
_default_width = true;
_layer = NULL;
_idx = 0;
_jct_id = -1;
_opcode = END_DECODE;
_wire_type = dbWireType::NONE;
_point_cnt = 0;
_property = 0;
_deltaX1 = 0;
_deltaY1 = 0;
_deltaX2 = 0;
_deltaY2 = 0;
}
inline unsigned char dbWireDecoder::nextOp(int& value)
{
ZASSERT(_idx < (int) _wire->length());
value = _wire->_data[_idx];
return _wire->_opcodes[_idx++];
}
inline unsigned char dbWireDecoder::nextOp(uint& value)
{
ZASSERT(_idx < (int) _wire->length());
value = (uint) _wire->_data[_idx];
return _wire->_opcodes[_idx++];
}
inline unsigned char dbWireDecoder::peekOp()
{
ZASSERT(_idx < (int) _wire->length());
return _wire->_opcodes[_idx];
}
//
// Flush the rule opcode if it exists here. The rule opcode that follows a point
// is used to speed up shape-id searches.
//
inline void dbWireDecoder::flushRule()
{
if (_idx != (int) _wire->_opcodes.size())
if ((_wire->_opcodes[_idx] & WOP_OPCODE_MASK) == WOP_RULE)
++_idx;
}
dbWireDecoder::OpCode dbWireDecoder::peek() const
{
ZASSERT(_wire);
int idx = _idx;
nextOpCode:
if (idx == (int) _wire->_opcodes.size())
return END_DECODE;
unsigned char opcode = _wire->_opcodes[idx];
switch (opcode & WOP_OPCODE_MASK) {
case WOP_PATH:
return PATH;
case WOP_SHORT:
return SHORT;
case WOP_JUNCTION:
return JUNCTION;
case WOP_RULE:
return RULE;
case WOP_X:
case WOP_Y:
case WOP_COLINEAR:
if (opcode & WOP_EXTENSION)
return POINT_EXT;
return POINT;
case WOP_VIA:
return VIA;
case WOP_TECH_VIA:
return TECH_VIA;
case WOP_ITERM:
return ITERM;
case WOP_BTERM:
return BTERM;
case WOP_RECT:
return RECT;
case WOP_VWIRE:
return VWIRE;
default:
++idx;
goto nextOpCode;
}
}
dbWireDecoder::OpCode dbWireDecoder::next()
{
ZASSERT(_wire);
nextOpCode:
if (_idx == (int) _wire->_opcodes.size())
return END_DECODE;
_jct_id = _idx;
unsigned char opcode = nextOp(_operand);
switch (opcode & WOP_OPCODE_MASK) {
case WOP_PATH: {
_layer = dbTechLayer::getTechLayer(_tech, _operand);
_point_cnt = 0;
_default_width = true;
switch (opcode & WOP_WIRE_TYPE_MASK) {
case WOP_NONE:
_wire_type = dbWireType::NONE;
break;
case WOP_COVER:
_wire_type = dbWireType::COVER;
break;
case WOP_FIXED:
_wire_type = dbWireType::FIXED;
break;
case WOP_ROUTED:
_wire_type = dbWireType::ROUTED;
break;
case WOP_NOSHIELD:
_wire_type = dbWireType::NOSHIELD;
break;
}
return _opcode = PATH;
}
case WOP_SHORT: {
_layer = dbTechLayer::getTechLayer(_tech, _operand);
_point_cnt = 0;
_default_width = true;
switch (opcode & WOP_WIRE_TYPE_MASK) {
case WOP_NONE:
_wire_type = dbWireType::NONE;
break;
case WOP_COVER:
_wire_type = dbWireType::COVER;
break;
case WOP_FIXED:
_wire_type = dbWireType::FIXED;
break;
case WOP_ROUTED:
_wire_type = dbWireType::ROUTED;
break;
case WOP_NOSHIELD:
_wire_type = dbWireType::NOSHIELD;
break;
}
// getjuction id
nextOp(_operand2);
return _opcode = SHORT;
}
case WOP_JUNCTION: {
WirePoint pnt;
getPrevPoint(
_tech, _block, _wire->_opcodes, _wire->_data, _operand, true, pnt);
_layer = pnt._layer;
_x = pnt._x;
_y = pnt._y;
_point_cnt = 0;
_default_width = true;
switch (opcode & WOP_WIRE_TYPE_MASK) {
case WOP_NONE:
_wire_type = dbWireType::NONE;
break;
case WOP_COVER:
_wire_type = dbWireType::COVER;
break;
case WOP_FIXED:
_wire_type = dbWireType::FIXED;
break;
case WOP_ROUTED:
_wire_type = dbWireType::ROUTED;
break;
case WOP_NOSHIELD:
_wire_type = dbWireType::NOSHIELD;
break;
}
return _opcode = JUNCTION;
}
case WOP_RULE:
_default_width = false;
_block_rule = (opcode & WOP_BLOCK_RULE);
return _opcode = RULE;
case WOP_X: {
_x = _operand;
if (_point_cnt == 0) {
_jct_id = _idx;
opcode = nextOp(_y);
_point_cnt = 1;
if (opcode & WOP_EXTENSION) {
nextOp(_operand2);
return _opcode = POINT_EXT;
}
return _opcode = POINT;
}
_point_cnt++;
if (opcode & WOP_EXTENSION) {
nextOp(_operand2);
_opcode = POINT_EXT;
} else
_opcode = POINT;
// if ( peekOp() == WOP_PROPERTY )
//{
// opcode = nextOp(_property);
// assert(opcode == WOP_PROPERTY);
//}
// else
_property = 0;
flushRule();
return _opcode;
}
case WOP_Y: {
ZASSERT(_point_cnt != 0);
_point_cnt++;
_y = _operand;
if (opcode & WOP_EXTENSION) {
nextOp(_operand2);
_opcode = POINT_EXT;
} else
_opcode = POINT;
// if ( peekOp() == WOP_PROPERTY )
//{
// opcode = nextOp(_property);
// assert(opcode == WOP_PROPERTY);
//}
// else
_property = 0;
flushRule();
return _opcode;
}
case WOP_COLINEAR: {
_point_cnt++;
if (opcode & WOP_EXTENSION) {
_operand2 = _operand;
_opcode = POINT_EXT;
} else
_opcode = POINT;
// if ( peekOp() == WOP_PROPERTY )
//{
// opcode = nextOp(_property);
// assert(opcode == WOP_PROPERTY);
//}
// else
_property = 0;
flushRule();
return _opcode;
}
case WOP_VIA: {
dbVia* via = dbVia::getVia(_block, _operand);
if (opcode & WOP_VIA_EXIT_TOP)
_layer = via->getTopLayer();
else
_layer = via->getBottomLayer();
return _opcode = VIA;
}
case WOP_TECH_VIA: {
dbTechVia* via = dbTechVia::getTechVia(_tech, _operand);
if (opcode & WOP_VIA_EXIT_TOP)
_layer = via->getTopLayer();
else
_layer = via->getBottomLayer();
return _opcode = TECH_VIA;
}
case WOP_RECT:
// order matches dbWireEncoder::addRect
_deltaX1 = _operand;
nextOp(_deltaY1);
nextOp(_deltaX2);
nextOp(_deltaY2);
return _opcode = RECT;
case WOP_ITERM:
return _opcode = ITERM;
case WOP_BTERM:
return _opcode = BTERM;
case WOP_OPERAND:
ZASSERT(DB_WIRE_DECODE_INVALID_OPCODE_SEQUENCE);
goto nextOpCode;
case WOP_PROPERTY:
goto nextOpCode;
case WOP_VWIRE: {
_layer = dbTechLayer::getTechLayer(_tech, _operand);
_point_cnt = 0;
_default_width = true;
switch (opcode & WOP_WIRE_TYPE_MASK) {
case WOP_NONE:
_wire_type = dbWireType::NONE;
break;
case WOP_COVER:
_wire_type = dbWireType::COVER;
break;
case WOP_FIXED:
_wire_type = dbWireType::FIXED;
break;
case WOP_ROUTED:
_wire_type = dbWireType::ROUTED;
break;
case WOP_NOSHIELD:
_wire_type = dbWireType::NOSHIELD;
break;
}
// getjuction id
nextOp(_operand2);
return _opcode = VWIRE;
}
case WOP_NOP:
goto nextOpCode;
default:
ZASSERT(DB_WIRE_DECODE_INVALID_OPCODE);
goto nextOpCode;
}
}
dbTechLayer* dbWireDecoder::getLayer() const
{
return _layer;
}
dbTechLayerRule* dbWireDecoder::getRule() const
{
ZASSERT(_opcode == RULE);
if (_block_rule) {
return dbTechLayerRule::getTechLayerRule(_block, _operand);
} else {
return dbTechLayerRule::getTechLayerRule(_tech, _operand);
}
}
void dbWireDecoder::getPoint(int& x, int& y) const
{
ZASSERT(_opcode == POINT);
x = _x;
y = _y;
}
void dbWireDecoder::getPoint(int& x, int& y, int& ext) const
{
ZASSERT(_opcode == POINT_EXT);
x = _x;
y = _y;
ext = _operand2;
}
uint dbWireDecoder::getProperty() const
{
ZASSERT(((_opcode == POINT) || (_opcode == POINT_EXT)) && (_point_cnt > 1));
return _property;
}
dbVia* dbWireDecoder::getVia() const
{
ZASSERT(_opcode == VIA);
dbVia* via = dbVia::getVia(_block, _operand);
return via;
}
dbTechVia* dbWireDecoder::getTechVia() const
{
ZASSERT(_opcode == TECH_VIA);
dbTechVia* via = dbTechVia::getTechVia(_tech, _operand);
return via;
}
void dbWireDecoder::getRect(int& deltaX1,
int& deltaY1,
int& deltaX2,
int& deltaY2) const
{
ZASSERT(_opcode == RECT);
deltaX1 = _deltaX1;
deltaY1 = _deltaY1;
deltaX2 = _deltaX2;
deltaY2 = _deltaY2;
}
dbITerm* dbWireDecoder::getITerm() const
{
ZASSERT(_opcode == ITERM);
dbITerm* iterm = dbITerm::getITerm(_block, _operand);
return iterm;
}
dbBTerm* dbWireDecoder::getBTerm() const
{
ZASSERT(_opcode == BTERM);
dbBTerm* bterm = dbBTerm::getBTerm(_block, _operand);
return bterm;
}
dbWireType dbWireDecoder::getWireType() const
{
ZASSERT((_opcode == PATH) || (_opcode == JUNCTION) || (_opcode == SHORT)
|| (_opcode == VWIRE));
return dbWireType((dbWireType::Value) _wire_type);
}
int dbWireDecoder::getJunctionId() const
{
return _jct_id;
}
int dbWireDecoder::getJunctionValue() const
{
ZASSERT((_opcode == JUNCTION) || (_opcode == SHORT) || (_opcode == VWIRE));
if (_opcode == SHORT || _opcode == VWIRE)
return _operand2;
return _operand;
}
void dumpDecoder4Net(dbNet* innet)
{
if (!innet)
return;
const char* prfx = "dumpDecoder:";
dbWire* wire0 = innet->getWire();
if (!wire0) {
warning(0, "%s No wires for net %s\n", prfx, innet->getName().c_str());
return;
}
dbWireDecoder decoder;
dbWireDecoder::OpCode opcode;
int x, y, ext;
decoder.begin(wire0);
notice(0, "%s begin decoder for net %s\n", prfx, innet->getName().c_str());
dbTechLayer* layer;
dbWireType wtype;
dbTechLayerRule* lyr_rule;
while (1) {
opcode = decoder.next();
if (opcode == dbWireDecoder::END_DECODE) {
notice(0, "%s End decoder for net %s\n", prfx, innet->getName().c_str());
break;
}
switch (opcode) {
case dbWireDecoder::PATH: {
layer = decoder.getLayer();
wtype = decoder.getWireType();
if (decoder.peek() == dbWireDecoder::RULE) {
opcode = decoder.next();
lyr_rule = decoder.getRule();
notice(0,
"%s New path: layer %s type %s non-default rule %s\n",
prfx,
layer->getName().c_str(),
wtype.getString(),
lyr_rule->getNonDefaultRule()->getName().c_str());
} else {
notice(0,
"%s New path: layer %s type %s\n",
prfx,
layer->getName().c_str(),
wtype.getString());
}
break;
}
case dbWireDecoder::JUNCTION: {
uint jct = decoder.getJunctionValue();
lyr_rule = NULL;
opcode = decoder.peek();
if (opcode == dbWireDecoder::RULE) {
opcode = decoder.next();
lyr_rule = decoder.getRule();
opcode = decoder.peek();
}
if (opcode == dbWireDecoder::POINT_EXT) {
opcode = decoder.next();
decoder.getPoint(x, y, ext);
if (lyr_rule)
notice(0,
"%s New path at junction %d, point(ext) %d %d %d, with rule "
"%s\n",
prfx,
jct,
x,
y,
ext,
lyr_rule->getNonDefaultRule()->getName().c_str());
else
notice(0,
"%s New path at junction %d, point(ext) %d %d %d\n",
prfx,
jct,
x,
y,
ext);
} else if (opcode == dbWireDecoder::POINT) {
opcode = decoder.next();
decoder.getPoint(x, y);
if (lyr_rule)
notice(0,
"%s New path at junction %d, point %d %d, with rule %s\n",
prfx,
jct,
x,
y,
lyr_rule->getNonDefaultRule()->getName().c_str());
else
notice(0,
"%s New path at junction %d, point %d %d\n",
prfx,
jct,
x,
y);
} else {
notice(0,
"%s opcode after junction is not point or point_ext??\n",
prfx);
}
break;
}
case dbWireDecoder::SHORT: {
uint jval = decoder.getJunctionValue();
layer = decoder.getLayer();
wtype = decoder.getWireType();
lyr_rule = NULL;
opcode = decoder.peek();
if (opcode == dbWireDecoder::RULE) {
opcode = decoder.next();
lyr_rule = decoder.getRule();
}
if (lyr_rule)
notice(0,
"%s Short at junction %d, with rule %s\n",
prfx,
jval,
lyr_rule->getNonDefaultRule()->getName().c_str());
else
notice(0, "%s Short at junction %d\n", prfx, jval);
break;
}
case dbWireDecoder::VWIRE: {
uint jval = decoder.getJunctionValue();
layer = decoder.getLayer();
wtype = decoder.getWireType();
lyr_rule = NULL;
opcode = decoder.peek();
if (opcode == dbWireDecoder::RULE) {
opcode = decoder.next();
lyr_rule = decoder.getRule();
}
if (lyr_rule)
notice(0,
"%s Virtual wire at junction %d, with rule %s\n",
prfx,
jval,
lyr_rule->getNonDefaultRule()->getName().c_str());
else
notice(0, "%s Virtual wire at junction %d\n", prfx, jval);
break;
}
case dbWireDecoder::POINT: {
decoder.getPoint(x, y);
notice(0, "%s Found point %d %d\n", prfx, x, y);
break;
}
case dbWireDecoder::POINT_EXT: {
decoder.getPoint(x, y, ext);
notice(0, "%s Found point(ext) %d %d %d\n", prfx, x, y, ext);
break;
}
case dbWireDecoder::TECH_VIA: {
notice(0,
"%s Found via %s\n",
prfx,
decoder.getTechVia()->getName().c_str());
break;
}
case dbWireDecoder::VIA: {
error(0, "block via found in signal net!\n");
break;
}
case dbWireDecoder::RECT: {
int deltaX1;
int deltaY1;
int deltaX2;
int deltaY2;
decoder.getRect(deltaX1, deltaY1, deltaX2, deltaY2);
break;
}
case dbWireDecoder::ITERM: {
notice(0, "%s Found Iterm\n", prfx);
break;
}
case dbWireDecoder::BTERM: {
notice(0, "%s Found Bterm\n", prfx);
break;
}
case dbWireDecoder::RULE: {
if (strcmp(
lyr_rule->getNonDefaultRule()->getName().c_str(),
(decoder.getRule())->getNonDefaultRule()->getName().c_str())) {
error(0,
"%s GOT RULE %s, EXPECTED RULE %s\n",
prfx,
lyr_rule->getNonDefaultRule()->getName().c_str(),
decoder.getRule()->getNonDefaultRule()->getName().c_str());
}
lyr_rule = decoder.getRule();
notice(0,
"%s Found Rule %s in middle of path\n",
prfx,
lyr_rule->getNonDefaultRule()->getName().c_str());
break;
}
case dbWireDecoder::END_DECODE:
notice(
0, "%s End decoder for net %s\n", prfx, innet->getName().c_str());
break;
default: {
error(0, "%s Hit default!\n", prfx);
break;
}
} // switch opcode
} // while
}
void dumpDecoder(dbBlock* inblk, const char* net_name_or_id)
{
const char* prfx = "dumpDecoder:";
if (!inblk || !net_name_or_id) {
error(0, "%s Must specify DB Block and either net name or ID\n", prfx);
return;
}
dbNet* innet = NULL;
const char* ckdigit;
for (ckdigit = net_name_or_id; *ckdigit; ckdigit++)
if (!isdigit(*ckdigit))
break;
innet = (*ckdigit == '\0') ? dbNet::getNet(inblk, atoi(net_name_or_id))
: inblk->findNet(net_name_or_id);
if (!innet) {
error(0, "%s Net %s not found\n", prfx, net_name_or_id);
return;
}
dumpDecoder4Net(innet);
}
} // namespace odb