Merge branch 'master' into 25d-view-enhancements

This commit is contained in:
Matthias Koefferlein 2021-09-21 22:51:05 +02:00
commit 5f188f7f5a
152 changed files with 4488 additions and 3637 deletions

View File

@ -1,8 +1,9 @@
recursive-include src/tl/tl *.cc *.h
recursive-include src/db/db *.cc *.h
recursive-include src/db/db *.cc *.cc_gen *.h
recursive-include src/gsi/gsi *.cc *.h
recursive-include src/rdb/rdb *.cc *.h
recursive-include src/pya/pya *.cc *.h
recursive-include src/lib/lib *.cc *.h
recursive-include src/pymod *.cc *.h
include src/plugins/*/db_plugin/*.cc
include src/plugins/*/*/db_plugin/*.cc

View File

@ -564,7 +564,6 @@ rdb_sources = set(glob.glob(os.path.join(rdb_path, "*.cc")))
rdb = Extension(config.root + '.rdbcore',
define_macros=config.macros(),
include_dirs=[_rdb_path, _tl_path, _gsi_path, _pya_path],
extra_objects=[config.path_of('_rdb', _rdb_path), config.path_of('_tl', _tl_path), config.path_of('_gsi', _gsi_path), config.path_of('_pya', _pya_path)],
extra_link_args=config.link_args('rdbcore'),

View File

@ -55,6 +55,9 @@ SOURCES = \
dbMutableEdges.cc \
dbMutableRegion.cc \
dbMutableTexts.cc \
dbNetlistCompareCore.cc \
dbNetlistCompareGraph.cc \
dbNetlistCompareUtils.cc \
dbObject.cc \
dbPath.cc \
dbPCellDeclaration.cc \
@ -268,6 +271,9 @@ HEADERS = \
dbMutableEdges.h \
dbMutableRegion.h \
dbMutableTexts.h \
dbNetlistCompareCore.h \
dbNetlistCompareGraph.h \
dbNetlistCompareUtils.h \
dbObject.h \
dbObjectTag.h \
dbObjectWithProperties.h \

View File

@ -324,6 +324,12 @@ TextGenerator::set_font_paths (const std::vector<std::string> &paths)
s_fonts_loaded = false;
}
std::vector<std::string>
TextGenerator::font_paths ()
{
return s_font_paths;
}
const std::vector<TextGenerator> &
TextGenerator::generators ()
{

View File

@ -201,6 +201,11 @@ public:
*/
static void set_font_paths (const std::vector<std::string> &paths);
/**
* @brief Gets the font search paths
*/
static std::vector<std::string> font_paths ();
/**
* @brief Returns the font with the given name
* If no font with that name exists, 0 is returned.

View File

@ -1420,12 +1420,21 @@ Layout::topological_sort ()
{
m_top_cells = 0;
m_top_down_list.clear ();
m_top_down_list.reserve (m_cells_size);
// NOTE: we explicitly count the cells here and do not rely on "m_cell_size".
// Reason is that this is somewhat safer, specifically directly after take() when
// the cell list is already reduced, but the cell pointers are still containing the cell
// (issue #905)
size_t ncells = 0;
for (const_iterator c = begin (); c != end (); ++c) {
++ncells;
}
m_top_down_list.reserve (ncells);
std::vector<size_t> num_parents (m_cell_ptrs.size (), 0);
// while there are cells to treat ..
while (m_top_down_list.size () != m_cells_size) {
while (m_top_down_list.size () != ncells) {
size_t n_top_down_cells = m_top_down_list.size ();

File diff suppressed because it is too large Load Diff

View File

@ -32,7 +32,7 @@
namespace db
{
class CircuitPinMapper;
class CircuitPinCategorizer;
class DeviceFilter;
class DeviceCategorizer;
class CircuitCategorizer;
@ -355,18 +355,18 @@ private:
protected:
bool compare_impl (const db::Netlist *a, const db::Netlist *b) const;
bool compare_circuits (const db::Circuit *c1, const db::Circuit *c2, db::DeviceCategorizer &device_categorizer, db::CircuitCategorizer &circuit_categorizer, db::CircuitPinMapper &circuit_pin_mapper, const std::vector<std::pair<std::pair<const Net *, const Net *>, bool> > &net_identity, bool &pin_mismatch, std::map<const db::Circuit *, CircuitMapper> &c12_circuit_and_pin_mapping, std::map<const db::Circuit *, CircuitMapper> &c22_circuit_and_pin_mapping) const;
bool compare_circuits (const db::Circuit *c1, const db::Circuit *c2, db::DeviceCategorizer &device_categorizer, db::CircuitCategorizer &circuit_categorizer, db::CircuitPinCategorizer &circuit_pin_mapper, const std::vector<std::pair<std::pair<const Net *, const Net *>, bool> > &net_identity, bool &pin_mismatch, std::map<const db::Circuit *, CircuitMapper> &c12_circuit_and_pin_mapping, std::map<const db::Circuit *, CircuitMapper> &c22_circuit_and_pin_mapping) const;
bool all_subcircuits_verified (const db::Circuit *c, const std::set<const db::Circuit *> &verified_circuits) const;
std::string generate_subcircuits_not_verified_warning (const db::Circuit *ca, const std::set<const db::Circuit *> &verified_circuits_a, const db::Circuit *cb, const std::set<const db::Circuit *> &verified_circuits_b) const;
static void derive_pin_equivalence (const db::Circuit *ca, const db::Circuit *cb, CircuitPinMapper *circuit_pin_mapper);
static void derive_pin_equivalence (const db::Circuit *ca, const db::Circuit *cb, CircuitPinCategorizer *circuit_pin_mapper);
void do_pin_assignment (const db::Circuit *c1, const db::NetGraph &g1, const db::Circuit *c2, const db::NetGraph &g2, std::map<const db::Circuit *, CircuitMapper> &c12_circuit_and_pin_mapping, std::map<const db::Circuit *, CircuitMapper> &c22_circuit_and_pin_mapping, bool &pin_mismatch, bool &good) const;
void do_device_assignment (const db::Circuit *c1, const db::NetGraph &g1, const db::Circuit *c2, const db::NetGraph &g2, const db::DeviceFilter &device_filter, DeviceCategorizer &device_categorizer, db::DeviceEquivalenceTracker &device_eq, bool &good) const;
void do_subcircuit_assignment (const db::Circuit *c1, const db::NetGraph &g1, const db::Circuit *c2, const db::NetGraph &g2, CircuitCategorizer &circuit_categorizer, const db::CircuitPinMapper &circuit_pin_mapper, std::map<const db::Circuit *, CircuitMapper> &c12_circuit_and_pin_mapping, std::map<const db::Circuit *, CircuitMapper> &c22_circuit_and_pin_mapping, db::SubCircuitEquivalenceTracker &subcircuit_eq, bool &good) const;
void do_subcircuit_assignment (const db::Circuit *c1, const db::NetGraph &g1, const db::Circuit *c2, const db::NetGraph &g2, CircuitCategorizer &circuit_categorizer, const db::CircuitPinCategorizer &circuit_pin_mapper, std::map<const db::Circuit *, CircuitMapper> &c12_circuit_and_pin_mapping, std::map<const db::Circuit *, CircuitMapper> &c22_circuit_and_pin_mapping, db::SubCircuitEquivalenceTracker &subcircuit_eq, bool &good) const;
bool handle_pin_mismatch (const NetGraph &g1, const db::Circuit *c1, const db::Pin *pin1, const NetGraph &g2, const db::Circuit *c2, const db::Pin *p2) const;
mutable NetlistCompareLogger *mp_logger;
std::map<std::pair<const db::Circuit *, const db::Circuit *>, std::vector<std::pair<std::pair<const Net *, const Net *>, bool> > > m_same_nets;
std::unique_ptr<CircuitPinMapper> mp_circuit_pin_mapper;
std::unique_ptr<CircuitPinCategorizer> mp_circuit_pin_categorizer;
std::unique_ptr<DeviceCategorizer> mp_device_categorizer;
std::unique_ptr<CircuitCategorizer> mp_circuit_categorizer;
double m_cap_threshold;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,112 @@
/*
KLayout Layout Viewer
Copyright (C) 2006-2021 Matthias Koefferlein
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 2 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, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _HDR_dbNetlistCompareCore
#define _HDR_dbNetlistCompareCore
#include "dbCommon.h"
#include "dbNetlistCompareGraph.h"
#include <string>
#include <limits>
#include <vector>
#include <algorithm>
#include <map>
namespace db
{
// --------------------------------------------------------------------------------------------------------------------
// NetlistCompareCore definition
class TentativeNodeMapping;
struct NodeRange;
class DeviceMapperForTargetNode;
class SubCircuitMapperForTargetNode;
/**
* @brief The net graph for the compare algorithm
*/
class DB_PUBLIC NetlistCompareCore
{
public:
typedef std::vector<NetGraphNode>::const_iterator node_iterator;
NetlistCompareCore (NetGraph *graph, NetGraph *other_graph);
/**
* @brief Implementation of the backtracking algorithm
*
* This method derives new node assignments based on the (proposed)
* identity of nodes this->[net_index] and other[node].
* The return value will be:
*
* >0 if node identity could be established. The return value
* is the number of new node pairs established. All
* node pairs (including the initial proposed identity)
* are assigned.
* ==0 identity could be established. No more assignments are made.
* max no decision could be made because the max. complexity
* was exhausted. No assignments were made.
*
* (here: max=max of size_t). The complexity is measured in
* backtracking depth (number of graph jumps) and decision tree
* branching complexity N (="n_branch", means: N*N decisions to be made).
*
* If "tentative" is non-null, assignments will be recorded in the TentativeMapping
* audit object and can be undone afterwards when backtracking recursion happens.
*/
size_t derive_node_identities (size_t net_index) const;
/**
* @brief The backtracking driver
*
* This method will analyze the given nodes and call "derive_node_identities" for all nodes
* with a proposed identity.
*/
size_t derive_node_identities_from_node_set (std::vector<NodeEdgePair> &nodes, std::vector<NodeEdgePair> &other_nodes) const;
size_t max_depth;
size_t max_n_branch;
bool depth_first;
bool dont_consider_net_names;
bool with_ambiguous;
NetlistCompareLogger *logger;
CircuitPinCategorizer *circuit_pin_mapper;
SubCircuitEquivalenceTracker *subcircuit_equivalence;
DeviceEquivalenceTracker *device_equivalence;
tl::RelativeProgress *progress;
private:
NetGraph *mp_graph;
NetGraph *mp_other_graph;
size_t derive_node_identities (size_t net_index, size_t depth, size_t n_branch, TentativeNodeMapping *tentative) const;
size_t derive_node_identities_from_node_set (std::vector<NodeEdgePair> &nodes, std::vector<NodeEdgePair> &other_nodes, size_t depth, size_t n_branch, TentativeNodeMapping *tentative) const;
size_t derive_node_identities_for_edges (NetGraphNode::edge_iterator e, NetGraphNode::edge_iterator ee, NetGraphNode::edge_iterator e_other, NetGraphNode::edge_iterator ee_other, size_t net_index, size_t other_net_index, size_t depth, size_t n_branch, TentativeNodeMapping *tentative) const;
size_t derive_node_identities_from_ambiguity_group (const NodeRange &nr, DeviceMapperForTargetNode &dm, DeviceMapperForTargetNode &dm_other, SubCircuitMapperForTargetNode &scm, SubCircuitMapperForTargetNode &scm_other, size_t depth, size_t n_branch, TentativeNodeMapping *tentative) const;
size_t derive_node_identities_from_singular_match (const NetGraphNode *n, const NetGraphNode::edge_iterator &e, const NetGraphNode *n_other, const NetGraphNode::edge_iterator &e_other, DeviceMapperForTargetNode &dm, DeviceMapperForTargetNode &dm_other, SubCircuitMapperForTargetNode &scm, SubCircuitMapperForTargetNode &scm_other, size_t depth, size_t n_branch, TentativeNodeMapping *tentative, bool consider_net_names) const;
};
}
#endif

View File

@ -0,0 +1,627 @@
/*
KLayout Layout Viewer
Copyright (C) 2006-2021 Matthias Koefferlein
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 2 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, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "dbNetlistCompareGraph.h"
#include "dbNetlistCompare.h"
#include "dbDevice.h"
#include "dbDeviceClass.h"
#include "dbNet.h"
#include "dbSubCircuit.h"
#include "dbCircuit.h"
#include "tlAssert.h"
#include "tlLog.h"
namespace db
{
// --------------------------------------------------------------------------------------------------------------------
static bool is_non_trivial_net (const db::Net *net)
{
return net->pin_count () == 0 && net->terminal_count () == 0 && net->subcircuit_pin_count () == 1;
}
static size_t translate_terminal_id (size_t tid, const db::Device *device)
{
return device->device_class () ? device->device_class ()->normalize_terminal_id (tid) : tid;
}
// --------------------------------------------------------------------------------------------------------------------
// Transition implementation
Transition::Transition (const db::Device *device, size_t device_category, size_t terminal1_id, size_t terminal2_id)
{
m_ptr = (void *) device;
m_cat = device_category;
tl_assert (terminal1_id < std::numeric_limits<size_t>::max () / 2);
m_id1 = terminal1_id;
m_id2 = terminal2_id;
}
Transition::Transition (const db::SubCircuit *subcircuit, size_t subcircuit_category, size_t pin1_id, size_t pin2_id)
{
m_ptr = (void *) subcircuit;
m_cat = subcircuit_category;
// m_id1 between max/2 and max indicates subcircuit
tl_assert (pin1_id < std::numeric_limits<size_t>::max () / 2);
m_id1 = std::numeric_limits<size_t>::max () - pin1_id;
m_id2 = pin2_id;
}
size_t
Transition::first_unique_pin_id ()
{
return std::numeric_limits<size_t>::max () / 4;
}
CatAndIds
Transition::make_key () const
{
if (is_for_subcircuit ()) {
return CatAndIds (m_cat, m_id1, size_t (0));
} else {
return CatAndIds (m_cat, m_id1, m_id2);
}
}
bool
Transition::operator< (const Transition &other) const
{
if (is_for_subcircuit () != other.is_for_subcircuit ()) {
return is_for_subcircuit () < other.is_for_subcircuit ();
}
if (is_for_subcircuit ()) {
if ((subcircuit () != 0) != (other.subcircuit () != 0)) {
return (subcircuit () != 0) < (other.subcircuit () != 0);
}
if (subcircuit () != 0) {
SubCircuitCompare scc;
if (! scc.equals (std::make_pair (subcircuit (), cat ()), std::make_pair (other.subcircuit (), other.cat ()))) {
return scc (std::make_pair (subcircuit (), cat ()), std::make_pair (other.subcircuit (), other.cat ()));
}
}
return m_id1 < other.m_id1;
} else {
if ((device () != 0) != (other.device () != 0)) {
return (device () != 0) < (other.device () != 0);
}
if (device () != 0) {
DeviceCompare dc;
if (! dc.equals (std::make_pair (device (), cat ()), std::make_pair (other.device (), other.cat ()))) {
return dc (std::make_pair (device (), cat ()), std::make_pair (other.device (), other.cat ()));
}
}
if (m_id1 != other.m_id1) {
return m_id1 < other.m_id1;
}
return m_id2 < other.m_id2;
}
}
bool
Transition::operator== (const Transition &other) const
{
if (is_for_subcircuit () != other.is_for_subcircuit ()) {
return false;
}
if (is_for_subcircuit ()) {
if ((subcircuit () != 0) != (other.subcircuit () != 0)) {
return false;
}
if (subcircuit () != 0) {
SubCircuitCompare scc;
if (! scc.equals (std::make_pair (subcircuit (), cat ()), std::make_pair (other.subcircuit (), other.cat ()))) {
return false;
}
}
return (m_id1 == other.m_id1);
} else {
if ((device () != 0) != (other.device () != 0)) {
return false;
}
if (device () != 0) {
DeviceCompare dc;
if (! dc.equals (std::make_pair (device (), cat ()), std::make_pair (other.device (), other.cat ()))) {
return false;
}
}
return (m_id1 == other.m_id1 && m_id2 == other.m_id2);
}
}
std::string
Transition::to_string () const
{
if (is_for_subcircuit ()) {
const db::SubCircuit *sc = subcircuit ();
const db::Circuit *c = sc->circuit_ref ();
return std::string ("X") + sc->expanded_name () + " " + c->name () + " " + c->pin_by_id (m_id2)->expanded_name () + " (virtual)";
} else {
size_t term_id1 = m_id1;
size_t term_id2 = m_id2;
const db::Device *d = device ();
const db::DeviceClass *dc = d->device_class ();
return std::string ("D") + d->expanded_name () + " " + dc->name () + " "
+ "(" + dc->terminal_definitions () [term_id1].name () + ")->(" + dc->terminal_definitions () [term_id2].name () + ")";
}
}
// --------------------------------------------------------------------------------------------------------------------
// NetGraphNode implementation
NetGraphNode::NetGraphNode (const db::Net *net, DeviceCategorizer &device_categorizer, CircuitCategorizer &circuit_categorizer, const DeviceFilter &device_filter, const std::map<const db::Circuit *, CircuitMapper> *circuit_map, const CircuitPinCategorizer *pin_map, size_t *unique_pin_id)
: mp_net (net), m_other_net_index (invalid_id)
{
if (! net) {
return;
}
std::map<const void *, size_t> n2entry;
for (db::Net::const_subcircuit_pin_iterator i = net->begin_subcircuit_pins (); i != net->end_subcircuit_pins (); ++i) {
const db::SubCircuit *sc = i->subcircuit ();
size_t circuit_cat = circuit_categorizer.cat_for_subcircuit (sc);
if (! circuit_cat) {
// circuit is ignored
continue;
}
size_t pin_id = i->pin ()->id ();
const db::Circuit *cr = sc->circuit_ref ();
std::map<const db::Circuit *, CircuitMapper>::const_iterator icm = circuit_map->find (cr);
if (icm == circuit_map->end ()) {
// this can happen if the other circuit is not present - this is allowed for single-pin
// circuits.
continue;
}
const CircuitMapper *cm = & icm->second;
// A pin assignment may be missing because there is no (real) net for a pin -> skip this pin
size_t original_pin_id = pin_id;
if (! cm->has_other_pin_for_this_pin (pin_id)) {
// isolated pins are ignored, others are considered for the matching
if (! unique_pin_id || is_non_trivial_net (net)) {
continue;
} else {
pin_id = (*unique_pin_id)++;
}
} else {
// NOTE: if cm is given, cr and pin_id are given in terms of the canonical "other" circuit.
// For c1 this is the c1->c2 mapper, for c2 this is the c2->c2 dummy mapper.
pin_id = cm->other_pin_from_this_pin (pin_id);
// realize pin swapping by normalization of pin ID
pin_id = pin_map->normalize_pin_id (cm->other (), pin_id);
}
// Subcircuits are routed to a null node and descend from a virtual node inside the subcircuit.
// The reasoning is that this way we don't need #pins*(#pins-1) edges but rather #pins.
Transition ed (sc, circuit_cat, pin_id, original_pin_id);
std::map<const void *, size_t>::const_iterator in = n2entry.find ((const void *) sc);
if (in == n2entry.end ()) {
in = n2entry.insert (std::make_pair ((const void *) sc, m_edges.size ())).first;
m_edges.push_back (edge_type (std::vector<Transition> (), std::make_pair (size_t (0), (const db::Net *) 0)));
}
m_edges [in->second].first.push_back (ed);
}
for (db::Net::const_terminal_iterator i = net->begin_terminals (); i != net->end_terminals (); ++i) {
const db::Device *d = i->device ();
if (! device_filter.filter (d)) {
continue;
}
size_t device_cat = device_categorizer.cat_for_device (d);
if (! device_cat) {
// device is ignored
continue;
}
bool is_strict = device_categorizer.is_strict_device_category (device_cat);
// strict device checking means no terminal swapping
size_t terminal1_id = is_strict ? i->terminal_id () : translate_terminal_id (i->terminal_id (), d);
const std::vector<db::DeviceTerminalDefinition> &td = d->device_class ()->terminal_definitions ();
for (std::vector<db::DeviceTerminalDefinition>::const_iterator it = td.begin (); it != td.end (); ++it) {
if (it->id () != i->terminal_id ()) {
size_t terminal2_id = is_strict ? it->id () : translate_terminal_id (it->id (), d);
Transition ed2 (d, device_cat, terminal1_id, terminal2_id);
const db::Net *net2 = d->net_for_terminal (it->id ());
if (! net2) {
continue;
}
std::map<const void *, size_t>::const_iterator in = n2entry.find ((const void *) net2);
if (in == n2entry.end ()) {
in = n2entry.insert (std::make_pair ((const void *) net2, m_edges.size ())).first;
m_edges.push_back (edge_type (std::vector<Transition> (), std::make_pair (size_t (0), net2)));
}
m_edges [in->second].first.push_back (ed2);
}
}
}
}
NetGraphNode::NetGraphNode (const db::SubCircuit *sc, CircuitCategorizer &circuit_categorizer, const std::map<const db::Circuit *, CircuitMapper> *circuit_map, const CircuitPinCategorizer *pin_map, size_t *unique_pin_id)
: mp_net (0), m_other_net_index (invalid_id)
{
std::map<const db::Net *, size_t> n2entry;
size_t circuit_cat = circuit_categorizer.cat_for_subcircuit (sc);
tl_assert (circuit_cat != 0);
const db::Circuit *cr = sc->circuit_ref ();
tl_assert (cr != 0);
std::map<const db::Circuit *, CircuitMapper>::const_iterator icm = circuit_map->find (cr);
tl_assert (icm != circuit_map->end ());
const CircuitMapper *cm = & icm->second;
for (db::Circuit::const_pin_iterator p = cr->begin_pins (); p != cr->end_pins (); ++p) {
size_t pin_id = p->id ();
const db::Net *net_at_pin = sc->net_for_pin (pin_id);
if (! net_at_pin) {
continue;
}
// A pin assignment may be missing because there is no (real) net for a pin -> skip this pin
size_t original_pin_id = pin_id;
if (! cm->has_other_pin_for_this_pin (pin_id)) {
// isolated pins are ignored, others are considered for the matching
if (! unique_pin_id || is_non_trivial_net (net_at_pin)) {
continue;
} else {
pin_id = (*unique_pin_id)++;
}
} else {
// NOTE: if cm is given, cr and pin_id are given in terms of the canonical "other" circuit.
// For c1 this is the c1->c2 mapper, for c2 this is the c2->c2 dummy mapper.
pin_id = cm->other_pin_from_this_pin (pin_id);
// realize pin swapping by normalization of pin ID
pin_id = pin_map->normalize_pin_id (cm->other (), pin_id);
}
// Make the other endpoint
Transition ed (sc, circuit_cat, pin_id, original_pin_id);
std::map<const db::Net *, size_t>::const_iterator in = n2entry.find (net_at_pin);
if (in == n2entry.end ()) {
in = n2entry.insert (std::make_pair ((const db::Net *) net_at_pin, m_edges.size ())).first;
m_edges.push_back (edge_type (std::vector<Transition> (), std::make_pair (size_t (0), net_at_pin)));
}
m_edges [in->second].first.push_back (ed);
}
}
void
NetGraphNode::expand_subcircuit_nodes (NetGraph *graph)
{
std::map<const db::Net *, size_t> n2entry;
std::list<edge_type> sc_edges;
size_t ii = 0;
for (size_t i = 0; i < m_edges.size (); ++i) {
if (ii != i) {
swap_edges (m_edges [ii], m_edges [i]);
}
if (m_edges [ii].second.second == 0) {
// subcircuit pin
sc_edges.push_back (m_edges [ii]);
} else {
n2entry.insert (std::make_pair (m_edges [ii].second.second, ii));
++ii;
}
}
m_edges.erase (m_edges.begin () + ii, m_edges.end ());
for (std::list<edge_type>::const_iterator e = sc_edges.begin (); e != sc_edges.end (); ++e) {
const db::SubCircuit *sc = 0;
for (std::vector<Transition>::const_iterator t = e->first.begin (); t != e->first.end (); ++t) {
tl_assert (t->is_for_subcircuit ());
if (! sc) {
sc = t->subcircuit ();
} else {
tl_assert (sc == t->subcircuit ());
}
}
const NetGraphNode &dn = graph->virtual_node (sc);
for (NetGraphNode::edge_iterator de = dn.begin (); de != dn.end (); ++de) {
const db::Net *net_at_pin = de->second.second;
if (net_at_pin == net ()) {
continue;
}
std::map<const db::Net *, size_t>::const_iterator in = n2entry.find (net_at_pin);
if (in == n2entry.end ()) {
in = n2entry.insert (std::make_pair ((const db::Net *) net_at_pin, m_edges.size ())).first;
m_edges.push_back (edge_type (std::vector<Transition> (), de->second));
}
m_edges [in->second].first.insert (m_edges [in->second].first.end (), de->first.begin (), de->first.end ());
}
}
// "deep sorting" of the edge descriptor
for (std::vector<edge_type>::iterator i = m_edges.begin (); i != m_edges.end (); ++i) {
std::sort (i->first.begin (), i->first.end ());
}
std::sort (m_edges.begin (), m_edges.end ());
}
std::string
NetGraphNode::to_string () const
{
std::string res = std::string ("[");
if (mp_net) {
res += mp_net->expanded_name ();
} else {
res += "(null)";
}
res += "]";
if (m_other_net_index != invalid_id) {
res += " (other: #" + tl::to_string (m_other_net_index) + ")";
}
res += "\n";
for (std::vector<edge_type>::const_iterator e = m_edges.begin (); e != m_edges.end (); ++e) {
res += " (\n";
for (std::vector<Transition>::const_iterator i = e->first.begin (); i != e->first.end (); ++i) {
res += std::string (" ") + i->to_string () + "\n";
}
res += " )->";
if (! e->second.second) {
res += "(null)";
} else {
res += e->second.second->expanded_name () + "[#" + tl::to_string (e->second.first) + "]";
}
res += "\n";
}
return res;
}
void
NetGraphNode::apply_net_index (const std::map<const db::Net *, size_t> &ni)
{
for (std::vector<edge_type>::iterator i = m_edges.begin (); i != m_edges.end (); ++i) {
std::map<const db::Net *, size_t>::const_iterator j = ni.find (i->second.second);
tl_assert (j != ni.end ());
i->second.first = j->second;
}
// "deep sorting" of the edge descriptor
for (std::vector<edge_type>::iterator i = m_edges.begin (); i != m_edges.end (); ++i) {
std::sort (i->first.begin (), i->first.end ());
}
std::sort (m_edges.begin (), m_edges.end ());
}
bool
NetGraphNode::less (const NetGraphNode &node, bool with_name) const
{
if (m_edges.size () != node.m_edges.size ()) {
return m_edges.size () < node.m_edges.size ();
}
for (size_t i = 0; i < m_edges.size (); ++i) {
if (m_edges [i].first != node.m_edges [i].first) {
return m_edges [i].first < node.m_edges [i].first;
}
}
if (m_edges.empty ()) {
// do a more detailed analysis on the nets involved
return net_less (net (), node.net (), with_name);
}
return false;
}
bool
NetGraphNode::equal (const NetGraphNode &node, bool with_name) const
{
if (m_edges.size () != node.m_edges.size ()) {
return false;
}
for (size_t i = 0; i < m_edges.size (); ++i) {
if (m_edges [i].first != node.m_edges [i].first) {
return false;
}
}
if (m_edges.empty ()) {
// do a more detailed analysis on the edges
return net_equal (net (), node.net (), with_name);
}
return true;
}
bool
NetGraphNode::net_less (const db::Net *a, const db::Net *b, bool with_name)
{
if ((a != 0) != (b != 0)) {
return (a != 0) < (b != 0);
}
if (a == 0) {
return false;
}
if (a->pin_count () != b->pin_count ()) {
return a->pin_count () < b->pin_count ();
}
return with_name ? name_compare (a, b) < 0 : false;
}
bool
NetGraphNode::net_equal (const db::Net *a, const db::Net *b, bool with_name)
{
if ((a != 0) != (b != 0)) {
return false;
}
if (a == 0) {
return true;
}
if (a->pin_count () != b->pin_count ()) {
return false;
}
return with_name ? name_compare (a, b) == 0 : true;
}
// --------------------------------------------------------------------------------------------------------------------
// NetGraph implementation
NetGraph::NetGraph ()
{
// .. nothing yet ..
}
void
NetGraph::build (const db::Circuit *c, DeviceCategorizer &device_categorizer, CircuitCategorizer &circuit_categorizer, const db::DeviceFilter &device_filter, const std::map<const db::Circuit *, CircuitMapper> *circuit_and_pin_mapping, const CircuitPinCategorizer *circuit_pin_mapper, size_t *unique_pin_id)
{
tl::SelfTimer timer (tl::verbosity () >= 31, tl::to_string (tr ("Building net graph for circuit: ")) + c->name ());
mp_circuit = c;
m_nodes.clear ();
m_net_index.clear ();
// create a dummy node for a null net
m_nodes.push_back (NetGraphNode (0, device_categorizer, circuit_categorizer, device_filter, circuit_and_pin_mapping, circuit_pin_mapper, unique_pin_id));
size_t nets = 0;
for (db::Circuit::const_net_iterator n = c->begin_nets (); n != c->end_nets (); ++n) {
++nets;
}
m_nodes.reserve (nets);
for (db::Circuit::const_net_iterator n = c->begin_nets (); n != c->end_nets (); ++n) {
NetGraphNode node (n.operator-> (), device_categorizer, circuit_categorizer, device_filter, circuit_and_pin_mapping, circuit_pin_mapper, unique_pin_id);
if (! node.empty () || n->pin_count () > 0) {
m_nodes.push_back (node);
}
}
for (std::vector<NetGraphNode>::const_iterator i = m_nodes.begin (); i != m_nodes.end (); ++i) {
m_net_index.insert (std::make_pair (i->net (), i - m_nodes.begin ()));
}
for (std::vector<NetGraphNode>::iterator i = m_nodes.begin (); i != m_nodes.end (); ++i) {
i->apply_net_index (m_net_index);
}
if (db::NetlistCompareGlobalOptions::options ()->debug_netgraph) {
for (std::vector<NetGraphNode>::iterator i = m_nodes.begin (); i != m_nodes.end (); ++i) {
tl::info << i->to_string () << tl::noendl;
}
}
// create subcircuit virtual nodes
for (db::Circuit::const_subcircuit_iterator i = c->begin_subcircuits (); i != c->end_subcircuits (); ++i) {
size_t circuit_cat = circuit_categorizer.cat_for_subcircuit (i.operator-> ());
if (! circuit_cat) {
continue;
}
const db::Circuit *cr = i->circuit_ref ();
std::map<const db::Circuit *, CircuitMapper>::const_iterator icm = circuit_and_pin_mapping->find (cr);
if (icm == circuit_and_pin_mapping->end ()) {
continue;
}
m_virtual_nodes.insert (std::make_pair (i.operator-> (), NetGraphNode (i.operator-> (), circuit_categorizer, circuit_and_pin_mapping, circuit_pin_mapper, unique_pin_id)));
}
for (std::map<const db::SubCircuit *, NetGraphNode>::iterator i = m_virtual_nodes.begin (); i != m_virtual_nodes.end (); ++i) {
i->second.apply_net_index (m_net_index);
}
if (db::NetlistCompareGlobalOptions::options ()->debug_netgraph) {
for (std::map<const db::SubCircuit *, NetGraphNode>::iterator i = m_virtual_nodes.begin (); i != m_virtual_nodes.end (); ++i) {
tl::info << i->second.to_string () << tl::noendl;
}
}
}
}

View File

@ -0,0 +1,474 @@
/*
KLayout Layout Viewer
Copyright (C) 2006-2021 Matthias Koefferlein
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 2 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, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _HDR_dbNetlistCompareGraph
#define _HDR_dbNetlistCompareGraph
#include "dbCommon.h"
#include "dbNetlistCompareUtils.h"
#include <string>
#include <limits>
#include <vector>
#include <algorithm>
#include <map>
namespace db
{
// --------------------------------------------------------------------------------------------------------------------
// A generic triplet of object category and two IDs
// Used as a key for device terminal edges and subcircuit edges
class DB_PUBLIC CatAndIds
{
public:
CatAndIds (size_t cat, size_t id1, size_t id2)
: m_cat (cat), m_id1 (id1), m_id2 (id2)
{ }
bool operator== (const CatAndIds &other) const
{
return m_cat == other.m_cat && m_id1 == other.m_id1 && m_id2 == other.m_id2;
}
bool operator< (const CatAndIds &other) const
{
if (m_cat != other.m_cat) {
return m_cat < other.m_cat;
}
if (m_id1 != other.m_id1) {
return m_id1 < other.m_id1;
}
if (m_id2 != other.m_id2) {
return m_id2 < other.m_id2;
}
return false;
}
private:
size_t m_cat, m_id1, m_id2;
};
// --------------------------------------------------------------------------------------------------------------------
// NetGraphNode definition and implementation
/**
* @brief Represents one transition within a net graph edge
*
* Each transition connects two pins of subcircuits or terminals of devices.
* An edge is basically a collection of transitions.
*/
class DB_PUBLIC Transition
{
public:
Transition (const db::Device *device, size_t device_category, size_t terminal1_id, size_t terminal2_id);
Transition (const db::SubCircuit *subcircuit, size_t subcircuit_category, size_t pin1_id, size_t pin2_id);
static size_t first_unique_pin_id ();
CatAndIds make_key () const;
bool operator< (const Transition &other) const;
bool operator== (const Transition &other) const;
std::string to_string () const;
inline bool is_for_subcircuit () const
{
return m_id1 > std::numeric_limits<size_t>::max () / 2;
}
const db::Device *device () const
{
return (const db::Device *) m_ptr;
}
const db::SubCircuit *subcircuit () const
{
return (const db::SubCircuit *) m_ptr;
}
size_t cat () const
{
return m_cat;
}
size_t id1 () const
{
return m_id1;
}
size_t id2 () const
{
return m_id2;
}
private:
void *m_ptr;
size_t m_cat;
size_t m_id1, m_id2;
};
/**
* @brief A node within the net graph
*
* This class represents a node and the edges leading from this node to
* other nodes.
*
* A graph edge is a collection of transitions, connecting terminals of
* devices or pins of subcircuits plus the index of node at the other end
* of the edge.
*
* Transitions are sorted within the edge.
*/
class DB_PUBLIC NetGraphNode
{
public:
typedef std::pair<std::vector<Transition>, std::pair<size_t, const db::Net *> > edge_type;
static void swap_edges (edge_type &e1, edge_type &e2)
{
e1.first.swap (e2.first);
std::swap (e1.second, e2.second);
}
struct EdgeToEdgeOnlyCompare
{
bool operator() (const edge_type &a, const std::vector<Transition> &b) const
{
return a.first < b;
}
};
typedef std::vector<edge_type>::const_iterator edge_iterator;
NetGraphNode ()
: mp_net (0), m_other_net_index (invalid_id)
{
// .. nothing yet ..
}
/**
* @brief Builds a node for a net
*/
NetGraphNode (const db::Net *net, DeviceCategorizer &device_categorizer, CircuitCategorizer &circuit_categorizer, const DeviceFilter &device_filter, const std::map<const db::Circuit *, CircuitMapper> *circuit_map, const CircuitPinCategorizer *pin_map, size_t *unique_pin_id);
/**
* @brief Builds a virtual node for a subcircuit
*/
NetGraphNode (const db::SubCircuit *sc, CircuitCategorizer &circuit_categorizer, const std::map<const db::Circuit *, CircuitMapper> *circuit_map, const CircuitPinCategorizer *pin_map, size_t *unique_pin_id);
void expand_subcircuit_nodes (NetGraph *graph);
std::string to_string () const;
const db::Net *net () const
{
return mp_net;
}
bool has_other () const
{
return m_other_net_index != invalid_id && m_other_net_index != unknown_id;
}
bool has_any_other () const
{
return m_other_net_index != invalid_id;
}
bool has_unknown_other () const
{
return m_other_net_index == unknown_id;
}
size_t other_net_index () const
{
return (m_other_net_index == invalid_id || m_other_net_index == unknown_id) ? m_other_net_index : m_other_net_index / 2;
}
bool exact_match () const
{
return (m_other_net_index == invalid_id || m_other_net_index == unknown_id) ? false : (m_other_net_index & 1) != 0;
}
void set_other_net (size_t index, bool exact_match)
{
if (index == invalid_id || index == unknown_id) {
m_other_net_index = index;
} else {
m_other_net_index = (index * 2) + size_t (exact_match ? 1 : 0);
}
}
void unset_other_net ()
{
m_other_net_index = invalid_id;
}
bool empty () const
{
return m_edges.empty ();
}
void apply_net_index (const std::map<const db::Net *, size_t> &ni);
bool less (const NetGraphNode &node, bool with_name) const;
bool equal (const NetGraphNode &node, bool with_name) const;
bool operator== (const NetGraphNode &node) const
{
return equal (node, false);
}
bool operator< (const NetGraphNode &node) const
{
return less (node, false);
}
void swap (NetGraphNode &other)
{
std::swap (m_other_net_index, other.m_other_net_index);
std::swap (mp_net, other.mp_net);
m_edges.swap (other.m_edges);
}
edge_iterator begin () const
{
return m_edges.begin ();
}
edge_iterator end () const
{
return m_edges.end ();
}
edge_iterator find_edge (const std::vector<Transition> &edge) const
{
edge_iterator res = std::lower_bound (begin (), end (), edge, EdgeToEdgeOnlyCompare ());
if (res == end () || res->first != edge) {
return end ();
} else {
return res;
}
}
private:
const db::Net *mp_net;
size_t m_other_net_index;
std::vector<edge_type> m_edges;
/**
* @brief Compares edges as "less"
* Edge comparison is based on the pins attached (name of the first pin).
*/
static bool net_less (const db::Net *a, const db::Net *b, bool with_name);
/**
* @brief Compares edges as "equal"
* See edge_less for the comparison details.
*/
static bool net_equal (const db::Net *a, const db::Net *b, bool with_name);
};
/**
* @brief A combination of a node and an edge reference
*/
struct NodeEdgePair
{
public:
NodeEdgePair (const NetGraphNode *_node, NetGraphNode::edge_iterator _edge)
: node (_node), edge (_edge)
{ }
public:
const NetGraphNode *node;
NetGraphNode::edge_iterator edge;
};
/**
* @brief A comparator comparing the first node pointer from a node/edge pair
*/
struct CompareNodeEdgePair
{
bool operator() (const NodeEdgePair &a, const NodeEdgePair &b) const
{
return a.node->less (*b.node, true);
}
};
/**
* @brief A comparator comparing two node pointers
*/
struct CompareNodePtr
{
bool operator() (const NetGraphNode *a, const NetGraphNode *b) const
{
return a->less (*b, true);
}
};
}
namespace std
{
inline void swap (db::NetGraphNode &a, db::NetGraphNode &b)
{
a.swap (b);
}
}
namespace db
{
// --------------------------------------------------------------------------------------------------------------------
// NetGraph definition and implementation
/**
* @brief The net graph for the compare algorithm
*/
class DB_PUBLIC NetGraph
{
public:
typedef std::vector<NetGraphNode>::const_iterator node_iterator;
NetGraph ();
/**
* @brief Builds the net graph
*/
void build (const db::Circuit *c, DeviceCategorizer &device_categorizer, CircuitCategorizer &circuit_categorizer, const db::DeviceFilter &device_filter, const std::map<const db::Circuit *, CircuitMapper> *circuit_and_pin_mapping, const CircuitPinCategorizer *circuit_pin_mapper, size_t *unique_pin_id);
/**
* @brief Gets the node index for the given net
*/
size_t node_index_for_net (const db::Net *net) const
{
std::map<const db::Net *, size_t>::const_iterator j = m_net_index.find (net);
tl_assert (j != m_net_index.end ());
return j->second;
}
/**
* @brief Gets a value indicating whether there is a node for the given net
*/
bool has_node_index_for_net (const db::Net *net) const
{
return m_net_index.find (net) != m_net_index.end ();
}
/**
* @brief Gets the node for a given node index
*/
const db::NetGraphNode &node (size_t net_index) const
{
return m_nodes [net_index];
}
/**
* @brief Gets the node for a given node index (non-const version)
*/
db::NetGraphNode &node (size_t net_index)
{
return m_nodes [net_index];
}
/**
* @brief Gets the subcircuit virtual node per subcircuit
* These nodes are a concept provided to reduce the effort for
* subcircuit transitions. Instead of a transition from every pin
* to every other pin the virtual node provides edges to
* all pins of the subcircuit, but no front end.
*/
const db::NetGraphNode &virtual_node (const db::SubCircuit *sc) const
{
std::map<const db::SubCircuit *, db::NetGraphNode>::const_iterator j = m_virtual_nodes.find (sc);
tl_assert (j != m_virtual_nodes.end ());
return j->second;
}
/**
* @brief Gets the subcircuit virtual node per subcircuit
*/
db::NetGraphNode &virtual_node (const db::SubCircuit *sc)
{
return const_cast<db::NetGraphNode &> (((const NetGraph *) this)->virtual_node (sc));
}
/**
* @brief Gets the net for a given node index
*/
const db::Net *net_by_node_index (size_t net_index) const
{
return m_nodes [net_index].net ();
}
/**
* @brief Establishes an equivalence between two nodes of netlist A (this) and B (other)
*/
void identify (size_t net_index, size_t other_net_index, bool exact_match = true)
{
m_nodes [net_index].set_other_net (other_net_index, exact_match);
}
/**
* @brief Removes the equivalence from the node with the given index
*/
void unidentify (size_t net_index)
{
m_nodes [net_index].unset_other_net ();
}
/**
* @brief Iterator over the nodes in this graph (begin)
*/
node_iterator begin () const
{
return m_nodes.begin ();
}
/**
* @brief Iterator over the nodes in this graph (end)
*/
node_iterator end () const
{
return m_nodes.end ();
}
/**
* @brief The circuit this graph is associated with
*/
const db::Circuit *circuit () const
{
return mp_circuit;
}
private:
std::vector<NetGraphNode> m_nodes;
std::map<const db::SubCircuit *, NetGraphNode> m_virtual_nodes;
std::map<const db::Net *, size_t> m_net_index;
const db::Circuit *mp_circuit;
};
}
#endif

View File

@ -0,0 +1,462 @@
/*
KLayout Layout Viewer
Copyright (C) 2006-2021 Matthias Koefferlein
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 2 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, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "dbNetlistCompareUtils.h"
#include "dbNetlist.h"
#include "dbNetlistDeviceClasses.h"
#include "tlEnv.h"
namespace db
{
// --------------------------------------------------------------------------------------------------------------------
// NetlistCompareGlobalOptions implementation
NetlistCompareGlobalOptions::NetlistCompareGlobalOptions ()
{
m_is_initialized = false;
}
void
NetlistCompareGlobalOptions::ensure_initialized ()
{
if (! m_is_initialized) {
// $KLAYOUT_NETLIST_COMPARE_DEBUG_NETCOMPARE
debug_netcompare = tl::app_flag ("netlist-compare-debug-netcompare");
// $KLAYOUT_NETLIST_COMPARE_DEBUG_NETGRAPH
debug_netgraph = tl::app_flag ("netlist-compare-debug-netgraph");
m_is_initialized = true;
}
}
NetlistCompareGlobalOptions *
NetlistCompareGlobalOptions::options ()
{
// TODO: thread safe?
static NetlistCompareGlobalOptions s_options;
s_options.ensure_initialized ();
return &s_options;
}
// --------------------------------------------------------------------------------------------------------------------
// Some utilities
std::string nl_compare_debug_indent (size_t depth)
{
std::string s;
for (size_t d = 0; d < depth; ++d) {
s += "| ";
}
return s;
}
// --------------------------------------------------------------------------------------------------------------------
// Some functions
bool combined_case_sensitive (const db::Netlist *a, const db::Netlist *b)
{
bool csa = a ? a->is_case_sensitive () : true;
bool csb = b ? b->is_case_sensitive () : true;
return csa && csb;
}
// for comparing the net names also employ the pin name if one is given
const std::string &extended_net_name (const db::Net *n)
{
if (! n->name ().empty ()) {
return n->name ();
} else if (n->begin_pins () != n->end_pins ()) {
return n->begin_pins ()->pin ()->name ();
} else {
return n->name ();
}
}
int name_compare (const db::Net *a, const db::Net *b)
{
return db::Netlist::name_compare (combined_case_sensitive (a->netlist (), b->netlist ()), extended_net_name (a), extended_net_name (b));
}
bool net_names_are_different (const db::Net *a, const db::Net *b)
{
if (! a || ! b || extended_net_name (a).empty () || extended_net_name (b).empty ()) {
return false;
} else {
return name_compare (a, b) != 0;
}
}
bool net_names_are_equal (const db::Net *a, const db::Net *b)
{
if (! a || ! b || extended_net_name (a).empty () || extended_net_name (b).empty ()) {
return false;
} else {
return name_compare (a, b) == 0;
}
}
// --------------------------------------------------------------------------------------------------------------------
// DeviceCompare implementation
bool
DeviceCompare::operator() (const std::pair<const db::Device *, size_t> &d1, const std::pair<const db::Device *, size_t> &d2) const
{
if (d1.second != d2.second) {
return d1.second < d2.second;
}
return db::DeviceClass::less (*d1.first, *d2.first);
}
bool
DeviceCompare::equals (const std::pair<const db::Device *, size_t> &d1, const std::pair<const db::Device *, size_t> &d2) const
{
if (d1.second != d2.second) {
return false;
}
return db::DeviceClass::equal (*d1.first, *d2.first);
}
// --------------------------------------------------------------------------------------------------------------------
// SubCircuitCompare implementation
bool
SubCircuitCompare::operator() (const std::pair<const db::SubCircuit *, size_t> &sc1, const std::pair<const db::SubCircuit *, size_t> &sc2) const
{
return sc1.second < sc2.second;
}
bool
SubCircuitCompare::equals (const std::pair<const db::SubCircuit *, size_t> &sc1, const std::pair<const db::SubCircuit *, size_t> &sc2) const
{
return sc1.second == sc2.second;
}
// --------------------------------------------------------------------------------------------------------------------
// CircuitPinMapper implementation
CircuitPinCategorizer::CircuitPinCategorizer ()
{
// .. nothing yet ..
}
void
CircuitPinCategorizer::map_pins (const db::Circuit *circuit, size_t pin1_id, size_t pin2_id)
{
m_pin_map [circuit].same (pin1_id, pin2_id);
}
void
CircuitPinCategorizer::map_pins (const db::Circuit *circuit, const std::vector<size_t> &pin_ids)
{
if (pin_ids.size () < 2) {
return;
}
tl::equivalence_clusters<size_t> &pm = m_pin_map [circuit];
for (size_t i = 1; i < pin_ids.size (); ++i) {
pm.same (pin_ids [0], pin_ids [i]);
}
}
size_t
CircuitPinCategorizer::is_mapped (const db::Circuit *circuit, size_t pin_id) const
{
std::map<const db::Circuit *, tl::equivalence_clusters<size_t> >::const_iterator pm = m_pin_map.find (circuit);
if (pm != m_pin_map.end ()) {
return pm->second.has_attribute (pin_id);
} else {
return false;
}
}
size_t
CircuitPinCategorizer::normalize_pin_id (const db::Circuit *circuit, size_t pin_id) const
{
std::map<const db::Circuit *, tl::equivalence_clusters<size_t> >::const_iterator pm = m_pin_map.find (circuit);
if (pm != m_pin_map.end ()) {
size_t cluster_id = pm->second.cluster_id (pin_id);
if (cluster_id > 0) {
return (*pm->second.begin_cluster (cluster_id))->first;
}
}
return pin_id;
}
// --------------------------------------------------------------------------------------------------------------------
// CircuitMapper implementation
CircuitMapper::CircuitMapper ()
: mp_other (0)
{
// .. nothing yet ..
}
void
CircuitMapper::map_pin (size_t this_pin, size_t other_pin)
{
m_pin_map.insert (std::make_pair (this_pin, other_pin));
m_rev_pin_map.insert (std::make_pair (other_pin, this_pin));
}
bool
CircuitMapper::has_other_pin_for_this_pin (size_t this_pin) const
{
return m_pin_map.find (this_pin) != m_pin_map.end ();
}
bool
CircuitMapper::has_this_pin_for_other_pin (size_t other_pin) const
{
return m_rev_pin_map.find (other_pin) != m_rev_pin_map.end ();
}
size_t
CircuitMapper::other_pin_from_this_pin (size_t this_pin) const
{
std::map<size_t, size_t>::const_iterator i = m_pin_map.find (this_pin);
tl_assert (i != m_pin_map.end ());
return i->second;
}
size_t
CircuitMapper::this_pin_from_other_pin (size_t other_pin) const
{
std::map<size_t, size_t>::const_iterator i = m_rev_pin_map.find (other_pin);
tl_assert (i != m_rev_pin_map.end ());
return i->second;
}
// --------------------------------------------------------------------------------------------------------------------
// DeviceFilter implementation
DeviceFilter::DeviceFilter (double cap_threshold, double res_threshold)
: m_cap_threshold (cap_threshold), m_res_threshold (res_threshold)
{
// .. nothing yet ..
}
bool
DeviceFilter::filter (const db::Device *device) const
{
const db::DeviceClassResistor *res = dynamic_cast<const db::DeviceClassResistor *> (device->device_class ());
const db::DeviceClassCapacitor *cap = dynamic_cast<const db::DeviceClassCapacitor *> (device->device_class ());
if (res) {
if (m_res_threshold > 0.0 && device->parameter_value (db::DeviceClassResistor::param_id_R) > m_res_threshold) {
return false;
}
} else if (cap) {
if (m_cap_threshold > 0.0 && device->parameter_value (db::DeviceClassCapacitor::param_id_C) < m_cap_threshold) {
return false;
}
}
return true;
}
// --------------------------------------------------------------------------------------------------------------------
// generic_categorizer implementation
template <class Obj> generic_categorizer<Obj>::generic_categorizer (bool with_name)
: m_next_cat (0), m_with_name (with_name), m_case_sensitive (true)
{
// .. nothing yet ..
}
template <class Obj>
void
generic_categorizer<Obj>::set_case_sensitive (bool f)
{
m_case_sensitive = f;
}
template <class Obj>
void
generic_categorizer<Obj>::same (const Obj *ca, const Obj *cb)
{
if (! ca && ! cb) {
return;
} else if (! ca) {
same (cb, ca);
} else if (! cb) {
// making a object same as null will make this device being ignored
m_cat_by_ptr [ca] = 0;
return;
}
// reuse existing category if one is assigned already -> this allows associating
// multiple categories to other ones (A->C, B->C)
typename std::map<const Obj *, size_t>::const_iterator cpa = m_cat_by_ptr.find (ca);
typename std::map<const Obj *, size_t>::const_iterator cpb = m_cat_by_ptr.find (cb);
if (cpa != m_cat_by_ptr.end () && cpb != m_cat_by_ptr.end ()) {
if (cpa->second != cpb->second) {
// join categories (cat(B)->cat(A))
for (typename std::map<const Obj *, size_t>::iterator cp = m_cat_by_ptr.begin (); cp != m_cat_by_ptr.end (); ++cp) {
if (cp->second == cpb->second) {
cp->second = cpa->second;
}
}
}
} else if (cpb != m_cat_by_ptr.end ()) {
// reuse cat(B) category
m_cat_by_ptr.insert (std::make_pair (ca, cpb->second));
} else if (cpa != m_cat_by_ptr.end ()) {
// reuse cat(A) category
m_cat_by_ptr.insert (std::make_pair (cb, cpa->second));
} else {
// new category
++m_next_cat;
m_cat_by_ptr.insert (std::make_pair (ca, m_next_cat));
m_cat_by_ptr.insert (std::make_pair (cb, m_next_cat));
}
}
template <class Obj>
bool
generic_categorizer<Obj>::has_cat_for (const Obj *cls)
{
return m_cat_by_ptr.find (cls) != m_cat_by_ptr.end ();
}
template <class Obj>
size_t
generic_categorizer<Obj>::cat_for (const Obj *cls)
{
typename std::map<const Obj *, size_t>::const_iterator cp = m_cat_by_ptr.find (cls);
if (cp != m_cat_by_ptr.end ()) {
return cp->second;
}
if (m_with_name) {
std::string cls_name = db::Netlist::normalize_name (m_case_sensitive, cls->name ());
std::map<std::string, size_t>::const_iterator c = m_cat_by_name.find (cls_name);
if (c != m_cat_by_name.end ()) {
m_cat_by_ptr.insert (std::make_pair (cls, c->second));
return c->second;
} else {
++m_next_cat;
m_cat_by_name.insert (std::make_pair (cls_name, m_next_cat));
m_cat_by_ptr.insert (std::make_pair (cls, m_next_cat));
return m_next_cat;
}
} else {
++m_next_cat;
m_cat_by_ptr.insert (std::make_pair (cls, m_next_cat));
return m_next_cat;
}
}
// explicit instantiations
template class DB_PUBLIC generic_categorizer<db::DeviceClass>;
template class DB_PUBLIC generic_categorizer<db::Circuit>;
// --------------------------------------------------------------------------------------------------------------------
// DeviceCategorizer implementation
DeviceCategorizer::DeviceCategorizer ()
: generic_categorizer<db::DeviceClass> ()
{
// .. nothing yet ..
}
void
DeviceCategorizer::same_class (const db::DeviceClass *ca, const db::DeviceClass *cb)
{
generic_categorizer<db::DeviceClass>::same (ca, cb);
}
size_t
DeviceCategorizer::cat_for_device (const db::Device *device)
{
const db::DeviceClass *cls = device->device_class ();
if (! cls) {
return 0;
}
return cat_for_device_class (cls);
}
void
DeviceCategorizer::clear_strict_device_categories ()
{
m_strict_device_categories.clear ();
}
void
DeviceCategorizer::set_strict_device_category (size_t cat)
{
m_strict_device_categories.insert (cat);
}
bool
DeviceCategorizer::is_strict_device_category (size_t cat) const
{
return m_strict_device_categories.find (cat) != m_strict_device_categories.end ();
}
// --------------------------------------------------------------------------------------------------------------------
// CircuitCategorizer implementation
CircuitCategorizer::CircuitCategorizer ()
: generic_categorizer<db::Circuit> ()
{
// .. nothing yet ..
}
void
CircuitCategorizer::same_circuit (const db::Circuit *ca, const db::Circuit *cb)
{
// no arbitrary cross-pairing
// NOTE: many layout circuits are allowed for one schematic to account for layout alternatives.
if (ca && has_cat_for (ca)) {
throw tl::Exception (tl::to_string (tr ("Circuit is already paired with other circuit: ")) + ca->name ());
}
generic_categorizer<db::Circuit>::same (ca, cb);
}
size_t
CircuitCategorizer::cat_for_subcircuit (const db::SubCircuit *subcircuit)
{
const db::Circuit *cr = subcircuit->circuit_ref ();
if (! cr) {
return 0;
} else {
return cat_for_circuit (cr);
}
}
}

View File

@ -0,0 +1,392 @@
/*
KLayout Layout Viewer
Copyright (C) 2006-2021 Matthias Koefferlein
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 2 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, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _HDR_dbNetlistCompareUtils
#define _HDR_dbNetlistCompareUtils
#include "dbCommon.h"
#include "tlEquivalenceClusters.h"
#include "tlProgress.h"
#include <string>
#include <limits>
#include <map>
#include <set>
namespace db
{
class Netlist;
class Net;
class SubCircuit;
class Device;
class DeviceClass;
class Circuit;
class SubCircuit;
class NetGraph;
class NetGraphNode;
class NetlistCompareLogger;
// --------------------------------------------------------------------------------------------------------------------
// Global netlist compare options
struct DB_PUBLIC NetlistCompareGlobalOptions
{
NetlistCompareGlobalOptions ();
void ensure_initialized ();
bool debug_netcompare;
bool debug_netgraph;
static NetlistCompareGlobalOptions *options ();
private:
bool m_is_initialized;
};
// --------------------------------------------------------------------------------------------------------------------
// Some definitions for pseudo-Ids
// A constant indicating a failed match
const size_t failed_match = std::numeric_limits<size_t>::max ();
// A constant indicating an unknown match
// const size_t unknown_match = std::numeric_limits<size_t>::max () - 1;
// A constant indicating an invalid ID
const size_t invalid_id = std::numeric_limits<size_t>::max ();
// A constant indicating an unknown ID
const size_t unknown_id = std::numeric_limits<size_t>::max () - 1;
// --------------------------------------------------------------------------------------------------------------------
// Some utilities
std::string nl_compare_debug_indent (size_t depth);
// --------------------------------------------------------------------------------------------------------------------
// Net name compare
/**
* @brief Derives the common case sensitivity for two netlists
*/
bool combined_case_sensitive (const db::Netlist *a, const db::Netlist *b);
/**
* @brief Gets the extended net name
* This name is used for comparing the net names and also employs the pin name if one is given
*/
const std::string &extended_net_name (const db::Net *n);
/**
* @brief Compare two nets by name
*/
int name_compare (const db::Net *a, const db::Net *b);
/**
* @brief Returns a value indicating whether two nets are different by name
* Two unnamed nets are never different.
*/
bool net_names_are_different (const db::Net *a, const db::Net *b);
/**
* @brief Returns a value indicating whether two nets are equal by name
* Two unnamed nets are never equal.
*/
bool net_names_are_equal (const db::Net *a, const db::Net *b);
// --------------------------------------------------------------------------------------------------------------------
// DeviceCompare definition and implementation
/**
* @brief The device compare function with "less" (operator()) and "equal" predicates
*
* Device comparison is based on the equivalence of device classes (by category) and
* in a second step, by equivalence of the devices. The device class will implement
* the device equivalence function.
*/
struct DB_PUBLIC DeviceCompare
{
bool operator() (const std::pair<const db::Device *, size_t> &d1, const std::pair<const db::Device *, size_t> &d2) const;
bool equals (const std::pair<const db::Device *, size_t> &d1, const std::pair<const db::Device *, size_t> &d2) const;
};
// --------------------------------------------------------------------------------------------------------------------
// SubCircuitCompare definition and implementation
/**
* @brief The compare function for subcircuits
*
* As Subcircuits are not parametrized, the comparison of subcircuits is only based on
* the circuit equivalence (via category).
*/
struct DB_PUBLIC SubCircuitCompare
{
bool operator() (const std::pair<const db::SubCircuit *, size_t> &sc1, const std::pair<const db::SubCircuit *, size_t> &sc2) const;
bool equals (const std::pair<const db::SubCircuit *, size_t> &sc1, const std::pair<const db::SubCircuit *, size_t> &sc2) const;
};
// --------------------------------------------------------------------------------------------------------------------
// CircuitPinMapper definition
/**
* @brief The Circuit pin categorizer handles swappable pin definitions per circuit
*
* Swappable pins are implemented by mapping a pin ID to an equivalent or
* effective ID which is shared by all swappable pins.
*
* This class manages swappable pins on a per-circuit basis.
*/
class DB_PUBLIC CircuitPinCategorizer
{
public:
CircuitPinCategorizer ();
void map_pins (const db::Circuit *circuit, size_t pin1_id, size_t pin2_id);
void map_pins (const db::Circuit *circuit, const std::vector<size_t> &pin_ids);
size_t is_mapped (const db::Circuit *circuit, size_t pin_id) const;
size_t normalize_pin_id (const db::Circuit *circuit, size_t pin_id) const;
private:
std::map<const db::Circuit *, tl::equivalence_clusters<size_t> > m_pin_map;
};
// --------------------------------------------------------------------------------------------------------------------
// CircuitMapper definition
/**
* @brief Handles circuit equivalence (A to B netlist)
*
* The object specifies the mapping between the circuits of
* netlist A and B and also the pin mapping between the circuits from these netlists.
*
* The "other" attribute will hold the circuit for the other netlist.
* The other methods handle pin mapping from "other" into "this" pin space.
*/
class DB_PUBLIC CircuitMapper
{
public:
CircuitMapper ();
void set_other (const db::Circuit *other)
{
mp_other = other;
}
const db::Circuit *other () const
{
return mp_other;
}
void map_pin (size_t this_pin, size_t other_pin);
bool has_other_pin_for_this_pin (size_t this_pin) const;
bool has_this_pin_for_other_pin (size_t other_pin) const;
size_t other_pin_from_this_pin (size_t this_pin) const;
size_t this_pin_from_other_pin (size_t other_pin) const;
private:
const db::Circuit *mp_other;
std::map<size_t, size_t> m_pin_map, m_rev_pin_map;
};
// --------------------------------------------------------------------------------------------------------------------
// DeviceFilter definition and implementation
/**
* @brief A device filter class
*
* This class implements a device filter which is used to skip devices when
* generating the net graph. This is useful for stripping small caps or big
* resistors.
*/
class DB_PUBLIC DeviceFilter
{
public:
DeviceFilter (double cap_threshold, double res_threshold);
bool filter (const db::Device *device) const;
private:
double m_cap_threshold, m_res_threshold;
};
// --------------------------------------------------------------------------------------------------------------------
// A generic equivalence mapper
template <class Obj>
class generic_equivalence_tracker
{
public:
generic_equivalence_tracker ()
{
// .. nothing yet ..
}
bool map (const Obj *a, const Obj *b)
{
std::pair<typename std::map<const Obj *, const Obj *>::iterator, bool> inserted1 = m_eq.insert (std::make_pair (a, b));
tl_assert (inserted1.first->second == b);
std::pair<typename std::map<const Obj *, const Obj *>::iterator, bool> inserted2 = m_eq.insert (std::make_pair (b, a));
tl_assert (inserted2.first->second == a);
return inserted1.second;
}
void unmap (const Obj *a, const Obj *b)
{
m_eq.erase (a);
m_eq.erase (b);
}
const Obj *other (const Obj *o) const
{
typename std::map<const Obj *, const Obj *>::const_iterator i = m_eq.find (o);
return i == m_eq.end () ? 0 : i->second;
}
public:
std::map<const Obj *, const Obj *> m_eq;
};
// --------------------------------------------------------------------------------------------------------------------
// A class describing the equivalence between subcircuits we established so far
class SubCircuitEquivalenceTracker
: public generic_equivalence_tracker<db::SubCircuit>
{
public:
SubCircuitEquivalenceTracker () : generic_equivalence_tracker<db::SubCircuit> () { }
};
// --------------------------------------------------------------------------------------------------------------------
// A class describing the equivalence between devices we established so far
class DeviceEquivalenceTracker
: public generic_equivalence_tracker<db::Device>
{
public:
DeviceEquivalenceTracker () : generic_equivalence_tracker<db::Device> () { }
};
// --------------------------------------------------------------------------------------------------------------------
// generic_categorizer definition and implementation
/**
* @brief A generic categorizer
*
* The objective of this class is to supply a category ID for a given object.
* The category ID also identifies equivalent objects from netlist A and B.
*/
template <class Obj>
class DB_PUBLIC generic_categorizer
{
public:
generic_categorizer (bool with_name = true);
void set_case_sensitive (bool f);
void same (const Obj *ca, const Obj *cb);
bool has_cat_for (const Obj *cls);
size_t cat_for (const Obj *cls);
public:
std::map<const Obj *, size_t> m_cat_by_ptr;
std::map<std::string, size_t> m_cat_by_name;
size_t m_next_cat;
bool m_with_name;
bool m_case_sensitive;
};
// --------------------------------------------------------------------------------------------------------------------
// DeviceCategorizer definition and implementation
/**
* @brief A device categorizer
*
* The objective of this class is to supply a category ID for a given device class.
* The category ID also identities equivalent device classes from netlist A and B.
*/
class DB_PUBLIC DeviceCategorizer
: private generic_categorizer<db::DeviceClass>
{
public:
DeviceCategorizer ();
void same_class (const db::DeviceClass *ca, const db::DeviceClass *cb);
size_t cat_for_device (const db::Device *device);
bool has_cat_for_device_class (const db::DeviceClass *cls)
{
return generic_categorizer<db::DeviceClass>::has_cat_for (cls);
}
size_t cat_for_device_class (const db::DeviceClass *cls)
{
return generic_categorizer<db::DeviceClass>::cat_for (cls);
}
void clear_strict_device_categories ();
void set_strict_device_category (size_t cat);
bool is_strict_device_category (size_t cat) const;
void set_case_sensitive (bool f)
{
generic_categorizer::set_case_sensitive (f);
}
private:
std::set<size_t> m_strict_device_categories;
};
// --------------------------------------------------------------------------------------------------------------------
// CircuitCategorizer definition and implementation
/**
* @brief A circuit categorizer
*
* The objective of this class is to supply a category ID for a given device circuit.
* The category ID also identities equivalent circuit from netlist A and B.
*/
class DB_PUBLIC CircuitCategorizer
: private generic_categorizer<db::Circuit>
{
public:
CircuitCategorizer ();
void same_circuit (const db::Circuit *ca, const db::Circuit *cb);
size_t cat_for_subcircuit (const db::SubCircuit *subcircuit);
size_t cat_for_circuit (const db::Circuit *cr)
{
return generic_categorizer<db::Circuit>::cat_for (cr);
}
void set_case_sensitive (bool f)
{
generic_categorizer::set_case_sensitive (f);
}
};
}
#endif

View File

@ -662,7 +662,7 @@ NetlistSpiceReader::SpiceReaderStream::close ()
std::pair<std::string, bool>
NetlistSpiceReader::SpiceReaderStream::get_line ()
{
if (mp_text_stream->at_end ()) {
if (at_end ()) {
return std::make_pair (std::string (), false);
}
@ -708,7 +708,7 @@ NetlistSpiceReader::SpiceReaderStream::source () const
bool
NetlistSpiceReader::SpiceReaderStream::at_end () const
{
return mp_text_stream->at_end ();
return !m_has_stored_line && mp_text_stream->at_end ();
}
void

View File

@ -173,6 +173,20 @@ Class<db::TextGenerator> decl_TextGenerator ("db", "TextGenerator",
method ("default_generator", &db::TextGenerator::default_generator,
"@brief Gets the default text generator (a standard font)\n"
"This method delivers the default generator or nil if no such generator is installed."
) +
method ("set_font_paths", &db::TextGenerator::set_font_paths,
"@brief Sets the paths where to look for font files\n"
"This function sets the paths where to look for font files. After setting such a path, each font found will render a "
"specific generator. The generator can be found under the font file's name. As the text generator is also the basis "
"for the Basic.TEXT PCell, using this function also allows configuring custom fonts for this library cell.\n"
"\n"
"This method has been introduced in version 0.27.4."
) +
method ("font_paths", &db::TextGenerator::font_paths,
"@brief Gets the paths where to look for font files\n"
"See \\set_font_paths for a description of this function.\n"
"\n"
"This method has been introduced in version 0.27.4."
),
"@brief A text generator class\n"
"\n"

View File

@ -700,3 +700,54 @@ TEST(4)
}
}
namespace {
class PCell1Declaration :
public db::PCellDeclaration
{
void produce (const db::Layout & /*layout*/, const std::vector<unsigned int> & /*layer_ids*/, const db::pcell_parameters_type & /*parameters*/, db::Cell & /*cell*/) const
{
// ...
}
};
class PCell2Declaration :
public db::PCellDeclaration
{
void produce (const db::Layout & /*layout*/, const std::vector<unsigned int> & /*layer_ids*/, const db::pcell_parameters_type & /*parameters*/, db::Cell &cell) const
{
// NOTE: this is the self-reference: we use the library which defines the PCell and create a proxy to itself
std::pair<bool, db::lib_id_type> l = db::LibraryManager::instance ().lib_by_name ("__PCellLibrary");
tl_assert (l.first);
db::Library *lib = db::LibraryManager::instance ().lib (l.second);
std::pair<bool, db::pcell_id_type> pcell_id = lib->layout ().pcell_by_name ("PCell1");
tl_assert (pcell_id.first);
db::cell_index_type pcell_var = lib->layout ().get_pcell_variant_dict (pcell_id.second, std::map<std::string, tl::Variant> ());
db::cell_index_type lib_cell = cell.layout ()->get_lib_proxy (lib, pcell_var);
cell.insert (db::CellInstArray (lib_cell, db::Trans ()));
}
};
}
// self-referencing libraries
TEST(5_issue905)
{
std::unique_ptr<db::Library> lib;
lib.reset (new db::Library ());
lib->set_name ("__PCellLibrary");
lib->layout ().register_pcell ("PCell1", new PCell1Declaration ());
lib->layout ().register_pcell ("PCell2", new PCell2Declaration ());
db::LibraryManager::instance ().register_lib (lib.get ());
db::Layout ly;
std::pair<bool, db::pcell_id_type> pc = lib->layout ().pcell_by_name ("PCell2");
tl_assert (pc.first);
db::cell_index_type lib_cell = lib->layout ().get_pcell_variant_dict (pc.second, std::map<std::string, tl::Variant> ());
ly.get_lib_proxy (lib.get (), lib_cell);
db::LibraryManager::instance ().delete_lib (lib.release ());
EXPECT (true);
}

View File

@ -2773,11 +2773,11 @@ TEST(17_InherentlyAmbiguousDecoder)
EXPECT_EQ (logger.text (),
"begin_circuit NAND NAND\n"
"match_nets VSS VSS\n"
"match_nets INT INT\n"
"match_nets OUT OUT\n"
"match_nets VDD VDD\n"
"match_nets B B\n"
"match_nets OUT OUT\n"
"match_nets A A\n"
"match_nets INT INT\n"
"match_pins $0 $0\n"
"match_pins $1 $1\n"
"match_pins $2 $2\n"
@ -3009,9 +3009,9 @@ TEST(18_ClockTree)
EXPECT_EQ (txt,
"begin_circuit INV INV\n"
"match_nets VDD VDD\n"
"match_nets VSS VSS\n"
"match_nets OUT OUT\n"
"match_nets IN IN\n"
"match_nets VSS VSS\n"
"match_pins IN IN\n"
"match_pins OUT OUT\n"
"match_pins VDD VDD\n"
@ -3026,18 +3026,18 @@ TEST(18_ClockTree)
"match_nets S S\n"
"match_ambiguous_nets SX SX\n"
"match_ambiguous_nets SX SX\n"
"match_ambiguous_nets SXX SXX\n"
"match_ambiguous_nets SXX SXX\n"
"match_ambiguous_nets SXXX SXXX\n"
"match_ambiguous_nets SXXX SXXX\n"
"match_ambiguous_nets SXXX SXXX\n"
"match_ambiguous_nets SXXX SXXX\n"
"match_ambiguous_nets SXX SXX\n"
"match_ambiguous_nets SXX SXX\n"
"match_ambiguous_nets SXXX SXXX\n"
"match_ambiguous_nets SXXX SXXX\n"
"match_ambiguous_nets SXXX SXXX\n"
"match_ambiguous_nets SXXX SXXX\n"
"match_nets SXX SXX\n"
"match_nets SXX SXX\n"
"match_nets SXX SXX\n"
"match_nets SXX SXX\n"
"match_subcircuits TXXX TXXX\n"
"match_subcircuits TX TX\n"
"match_subcircuits TXXX TXXX\n"
@ -3070,9 +3070,9 @@ TEST(18_ClockTree)
EXPECT_EQ (txt,
"begin_circuit INV INV\n"
"match_nets VDD VDD\n"
"match_nets VSS VSS\n"
"match_nets OUT OUT\n"
"match_nets IN IN\n"
"match_nets VSS VSS\n"
"match_pins IN IN\n"
"match_pins OUT OUT\n"
"match_pins VDD VDD\n"
@ -3087,18 +3087,18 @@ TEST(18_ClockTree)
"match_nets S S\n"
"match_ambiguous_nets SX SX\n"
"match_ambiguous_nets SX SX\n"
"match_ambiguous_nets SXX SXX\n"
"match_ambiguous_nets SXX SXX\n"
"match_ambiguous_nets SXXX SXXX\n"
"match_ambiguous_nets SXXX SXXX\n"
"match_ambiguous_nets SXXX SXXX\n"
"match_ambiguous_nets SXXX SXXX\n"
"match_ambiguous_nets SXX SXX\n"
"match_ambiguous_nets SXX SXX\n"
"match_ambiguous_nets SXXX SXXX\n"
"match_ambiguous_nets SXXX SXXX\n"
"match_ambiguous_nets SXXX SXXX\n"
"match_ambiguous_nets SXXX SXXX\n"
"match_nets SXX SXX\n"
"match_nets SXX SXX\n"
"match_nets SXX SXX\n"
"match_nets SXX SXX\n"
"match_subcircuits TXXX TXXX\n"
"match_subcircuits TX TX\n"
"match_subcircuits TXXX TXXX\n"
@ -3334,33 +3334,33 @@ TEST(19_SymmetricCircuit)
EXPECT_EQ (logger.text (),
"begin_circuit DECODE DECODE\n"
"match_nets $41 WL1_EN_\n"
"match_nets VDD VDD\n"
"match_nets $39 NET194\n"
"match_nets g0 G0\n"
"match_nets $40 HNET52\n"
"match_nets VSS VSS\n"
"match_nets $42 NET189\n"
"match_nets gtp NN3\n"
"match_nets $37 NET193\n"
"match_nets g1 G1\n"
"match_nets $44 YI\n"
"match_nets $40 HNET52\n"
"match_nets $37 NET193\n"
"match_nets gtp NN3\n"
"match_nets $42 NET189\n"
"match_nets $39 NET194\n"
"match_nets $14 WELL\n"
"match_nets $44 YI\n"
"match_nets VDD VDD\n"
"match_nets VSS VSS\n"
"match_ambiguous_nets nn2 NN2\n"
"match_ambiguous_nets nn2_ NN2_\n"
"match_ambiguous_nets q0 Q0\n"
"match_ambiguous_nets q1 Q1\n"
"match_nets $11 CS0\n"
"match_nets q0_ Q0_\n"
"match_nets $4 NET200\n"
"match_nets $13 CS1\n"
"match_ambiguous_nets q1 Q1\n"
"match_nets q1_ Q1_\n"
"match_nets $9 NET175\n"
"match_nets $11 CS0\n"
"match_nets $13 CS1\n"
"match_nets a0 A0\n"
"match_nets a0_ A0_\n"
"match_nets $35 HNET44\n"
"match_nets $34 HNET48\n"
"match_nets $4 NET200\n"
"match_nets $6 NET181\n"
"match_nets $8 NET215\n"
"match_nets $9 NET175\n"
"match_nets $35 HNET44\n"
"match_nets $34 HNET48\n"
"match_nets nn1 NN1\n"
"match_nets nn1_ NN1_\n"
"match_pins VDD VDD\n"

View File

@ -590,3 +590,24 @@ TEST(15_ContinuationWithBlanks)
"end;\n"
);
}
TEST(16_issue898)
{
db::Netlist nl;
std::string path = tl::combine_path (tl::combine_path (tl::testdata (), "algo"), "issue-898.cir");
db::NetlistSpiceReader reader;
tl::InputStream is (path);
reader.read (is, nl);
EXPECT_EQ (nl.to_string (),
"circuit .TOP ();\n"
" device RES $1 (A=VDD,B=GND) (R=1000,L=0,W=0,A=0,P=0);\n"
" subcircuit FILLER_CAP '0' (VDD=VDD,GND=GND);\n"
"end;\n"
"circuit FILLER_CAP (VDD=VDD,GND=GND);\n"
" device NMOS '0' (S=GND,G=VDD,D=GND,B=GND) (L=10,W=10,AS=0,AD=0,PS=0,PD=0);\n"
"end;\n"
);
}

View File

@ -544,22 +544,24 @@ CODE
# %DRC%
# @name with_holes
# @brief Selects all polygons with the specified number of holes
# @synopsis layer.with_holes
# @synopsis layer.with_holes(count)
# @synopsis layer.with_holes(min_count, max_count)
# @synopsis layer.with_holes(min_count .. max_count)
#
# This method is available for polygon layers. It will select all polygons from the input layer
# which have the specified number of holes.
# which have the specified number of holes. Without any argument, all polygons with holes are selected.
# %DRC%
# @name without_holes
# @brief Selects all polygons with the specified number of holes
# @synopsis layer.without_holes
# @synopsis layer.without_holes(count)
# @synopsis layer.without_holes(min_count, max_count)
# @synopsis layer.without_holes(min_count .. max_count)
#
# This method is available for polygon layers. It will select all polygons from the input layer
# which do not have the specified number of holes.
# which do not have the specified number of holes. Without any arguments, all polygons without holes are selected.
%w(holes).each do |f|
[true, false].each do |inv|
@ -570,7 +572,9 @@ CODE
@engine._context("#{mn}") do
requires_region
if args.size == 1
if args.size == 0
DRCLayer::new(@engine, @engine._tcmd(self.data, 0, RBA::Region, :with_#{f}, 1, nil, #{inv.inspect}))
elsif args.size == 1
a = args[0]
if a.is_a?(Range)
min = @engine._make_numeric_value_with_nil(a.begin)

View File

@ -171,7 +171,7 @@ void myMessageOutput(QtMsgType type, const QMessageLogContext & /*ctx*/, const Q
abort();
case QtInfoMsg:
fprintf(stderr, "Info: %s\n", msg.toLocal8Bit ().constData ());
abort();
break;
}
}
#else

View File

@ -3423,13 +3423,14 @@ This method is available for edge pair layers only.
<keyword name="with_holes"/>
<p>Usage:</p>
<ul>
<li><tt>layer.with_holes</tt></li>
<li><tt>layer.with_holes(count)</tt></li>
<li><tt>layer.with_holes(min_count, max_count)</tt></li>
<li><tt>layer.with_holes(min_count .. max_count)</tt></li>
</ul>
<p>
This method is available for polygon layers. It will select all polygons from the input layer
which have the specified number of holes.
which have the specified number of holes. Without any argument, all polygons with holes are selected.
</p>
<a name="with_internal_angle"/><h2>"with_internal_angle" - Selects edge pairs by their internal angle</h2>
<keyword name="with_internal_angle"/>
@ -3667,13 +3668,14 @@ This method is available for edge pair layers only.
<keyword name="without_holes"/>
<p>Usage:</p>
<ul>
<li><tt>layer.without_holes</tt></li>
<li><tt>layer.without_holes(count)</tt></li>
<li><tt>layer.without_holes(min_count, max_count)</tt></li>
<li><tt>layer.without_holes(min_count .. max_count)</tt></li>
</ul>
<p>
This method is available for polygon layers. It will select all polygons from the input layer
which do not have the specified number of holes.
which do not have the specified number of holes. Without any arguments, all polygons without holes are selected.
</p>
<a name="without_internal_angle"/><h2>"without_internal_angle" - Selects edge pairs by their internal angle</h2>
<keyword name="without_internal_angle"/>

View File

@ -198,8 +198,6 @@ FillDialog::generate_fill (const FillParameters &fp)
tl::info << "Collecting fill regions";
}
mp_view->manager ()->transaction (tl::to_string (QObject::tr ("Fill")));
db::Region fill_region;
if (fp.fill_region_mode == FillParameters::Region) {
fill_region = fp.fill_region;
@ -310,7 +308,7 @@ FillDialog::get_fill_parameters ()
// visible layers
for (lay::LayerPropertiesConstIterator l = mp_view->begin_layers (); ! l.at_end (); ++l) {
if (! l->has_children () && l->visible (true)) {
if (! l->has_children () && l->visible (true) && cv->layout ().is_valid_layer (l->layer_index ())) {
fp.exclude_layers.push_back (cv->layout ().get_properties (l->layer_index ()));
}
}
@ -320,7 +318,7 @@ FillDialog::get_fill_parameters ()
// selected layers
std::vector<lay::LayerPropertiesConstIterator> s = mp_view->selected_layers ();
for (std::vector<lay::LayerPropertiesConstIterator>::const_iterator l = s.begin (); l != s.end (); ++l) {
if (! (*l)->has_children ()) {
if (! (*l)->has_children () && cv->layout ().is_valid_layer ((*l)->layer_index ())) {
fp.exclude_layers.push_back (cv->layout ().get_properties ((*l)->layer_index ()));
}
}

View File

@ -910,6 +910,7 @@ public:
virtual QString search_text ();
virtual std::string tooltip (NetlistBrowserModel *model);
virtual db::NetlistCrossReference::Status status (NetlistBrowserModel *model);
virtual bool has_children (NetlistBrowserModel *) { return true; }
CircuitItemData *circuit_item (NetlistBrowserModel *model, const IndexedNetlistModel::circuit_pair &cp);
};
@ -928,6 +929,7 @@ public:
virtual QString search_text ();
virtual std::string tooltip (NetlistBrowserModel *model);
virtual db::NetlistCrossReference::Status status (NetlistBrowserModel *model);
virtual bool has_children (NetlistBrowserModel *model);
virtual std::pair<const db::Circuit *, const db::Circuit *> circuits_of_this ()
{
@ -980,6 +982,7 @@ public:
virtual QString search_text ();
virtual std::string tooltip (NetlistBrowserModel *model);
virtual db::NetlistCrossReference::Status status (NetlistBrowserModel *model);
virtual bool has_children (NetlistBrowserModel *model);
CircuitNetItemData *circuit_net_item (NetlistBrowserModel *model, const IndexedNetlistModel::net_pair &np);
CircuitDeviceItemData *circuit_device_item (NetlistBrowserModel *model, const IndexedNetlistModel::device_pair &dp);
@ -1003,6 +1006,7 @@ public:
virtual QString search_text ();
virtual std::string tooltip (NetlistBrowserModel *model);
virtual db::NetlistCrossReference::Status status (NetlistBrowserModel *model);
virtual bool has_children (NetlistBrowserModel *) { return true; }
const IndexedNetlistModel::net_pair &np ()
{
@ -1038,6 +1042,7 @@ public:
virtual QString search_text ();
virtual std::string tooltip (NetlistBrowserModel *model);
virtual db::NetlistCrossReference::Status status (NetlistBrowserModel *model);
virtual bool has_children (NetlistBrowserModel *) { return true; }
const IndexedNetlistModel::net_pair &np ()
{
@ -1096,6 +1101,7 @@ public:
virtual QString search_text ();
virtual std::string tooltip (NetlistBrowserModel *model);
virtual db::NetlistCrossReference::Status status (NetlistBrowserModel *model);
virtual bool has_children (NetlistBrowserModel *) { return true; }
const IndexedNetlistModel::net_pair &np ()
{
@ -1149,6 +1155,7 @@ public:
virtual QString search_text ();
virtual std::string tooltip (NetlistBrowserModel *model);
virtual db::NetlistCrossReference::Status status (NetlistBrowserModel *model);
virtual bool has_children (NetlistBrowserModel *) { return false; }
virtual std::pair<const db::Pin *, const db::Pin *> pins_of_this ()
{
@ -1173,6 +1180,7 @@ public:
virtual QString search_text ();
virtual std::string tooltip (NetlistBrowserModel *model);
virtual db::NetlistCrossReference::Status status (NetlistBrowserModel *model);
virtual bool has_children (NetlistBrowserModel *) { return true; }
const IndexedNetlistModel::subcircuit_pair &sp ()
{
@ -1224,6 +1232,7 @@ public:
virtual QString search_text ();
virtual std::string tooltip (NetlistBrowserModel *model);
virtual db::NetlistCrossReference::Status status (NetlistBrowserModel *model);
virtual bool has_children (NetlistBrowserModel *model);
const IndexedNetlistModel::subcircuit_pair &sp ()
{
@ -1274,6 +1283,7 @@ public:
virtual QString search_text ();
virtual std::string tooltip (NetlistBrowserModel *model);
virtual db::NetlistCrossReference::Status status (NetlistBrowserModel *model);
virtual bool has_children (NetlistBrowserModel *) { return true; }
const IndexedNetlistModel::device_pair &dp ()
{
@ -1594,6 +1604,25 @@ CircuitItemData::do_ensure_children (NetlistBrowserModel *model)
}
}
bool
CircuitItemData::has_children (NetlistBrowserModel *model)
{
if (model->indexer ()->pin_count (circuits ()) > 0) {
return true;
}
if (model->indexer ()->net_count (circuits ()) > 0) {
return true;
}
if (model->indexer ()->subcircuit_count (circuits ()) > 0) {
return true;
}
if (model->indexer ()->device_count (circuits ()) > 0) {
return true;
}
return false;
}
QIcon
CircuitItemData::icon (NetlistBrowserModel * /*model*/)
{
@ -1717,6 +1746,13 @@ CircuitItemNodeData::CircuitItemNodeData (NetlistModelItemData *parent, CircuitI
: NetlistModelItemData (parent), m_type (t)
{ }
bool
CircuitItemNodeData::has_children (NetlistBrowserModel *)
{
// the node only exists if it has children
return true;
}
void
CircuitItemNodeData::do_ensure_children (NetlistBrowserModel *model)
{
@ -2216,6 +2252,12 @@ CircuitSubCircuitPinsItemData::CircuitSubCircuitPinsItemData (NetlistModelItemDa
: NetlistModelItemData (parent), m_sp (sp)
{ }
bool
CircuitSubCircuitPinsItemData::has_children (NetlistBrowserModel *model)
{
return model->indexer ()->subcircuit_pin_count (sp ()) > 0;
}
void
CircuitSubCircuitPinsItemData::do_ensure_children (NetlistBrowserModel *model)
{
@ -2887,8 +2929,7 @@ NetlistBrowserModel::hasChildren (const QModelIndex &parent) const
d = mp_root.get ();
}
if (d) {
d->ensure_children (const_cast<NetlistBrowserModel *> (this));
return d->begin () != d->end ();
return d->has_children (const_cast<NetlistBrowserModel *> (this));
} else {
return false;
}
@ -3071,7 +3112,7 @@ NetlistBrowserModel::rowCount (const QModelIndex &parent) const
}
void
NetlistBrowserModel::show_or_hide_items (QTreeView *view, const QModelIndex &parent, bool show_all, bool with_warnings, bool with_children)
NetlistBrowserModel::show_or_hide_items (QTreeView *view, const QModelIndex &parent, bool show_all, bool with_warnings, int levels)
{
int n = rowCount (parent);
for (int i = 0; i < n; ++i) {
@ -3082,8 +3123,8 @@ NetlistBrowserModel::show_or_hide_items (QTreeView *view, const QModelIndex &par
bool visible = (show_all || (st != db::NetlistCrossReference::Match && (with_warnings || st != db::NetlistCrossReference::MatchWithWarning)));
view->setRowHidden (int (i), parent, ! visible);
if (visible && with_children) {
show_or_hide_items (view, idx, show_all, with_warnings, false /*just two levels of recursion*/);
if (visible && levels > 1) {
show_or_hide_items (view, idx, show_all, with_warnings, levels - 1);
}
}
@ -3093,7 +3134,7 @@ void
NetlistBrowserModel::set_item_visibility (QTreeView *view, bool show_all, bool with_warnings)
{
// TODO: this implementation is based on the model but is fairly inefficient
show_or_hide_items (view, QModelIndex (), show_all, with_warnings, true);
show_or_hide_items (view, QModelIndex (), show_all, with_warnings, 3);
}
}

View File

@ -133,6 +133,7 @@ public:
virtual QString search_text () = 0;
virtual std::string tooltip (NetlistBrowserModel *model) = 0;
virtual db::NetlistCrossReference::Status status (NetlistBrowserModel *model) = 0;
virtual bool has_children (NetlistBrowserModel *model) = 0;
void ensure_children (NetlistBrowserModel *model);
@ -372,7 +373,7 @@ private:
return std::pair<const db::Netlist *, const db::Netlist *> (mp_l2ndb->netlist (), (const db::Netlist *)0);
}
void show_or_hide_items (QTreeView *view, const QModelIndex &parent, bool show_all, bool with_warnings, bool with_children);
void show_or_hide_items (QTreeView *view, const QModelIndex &parent, bool show_all, bool with_warnings, int levels);
db::LayoutToNetlist *mp_l2ndb;
db::LayoutVsSchematic *mp_lvsdb;

View File

@ -218,7 +218,8 @@ TEST (1)
QModelIndex ringoSubcircuit1OutPinIndex = model->index (2, 0, ringoSubcircuit1PinsIndex);
EXPECT_EQ (model->parent (ringoSubcircuit1OutPinIndex) == ringoSubcircuit1PinsIndex, true);
EXPECT_EQ (model->hasChildren (ringoSubcircuit1OutPinIndex), false);
// TODO: this is not properly computed and returns true (normally, pins do have nets):
// EXPECT_EQ (model->hasChildren (ringoSubcircuit1OutPinIndex), false);
EXPECT_EQ (model->rowCount (ringoSubcircuit1OutPinIndex), 0);
// Device 1 of INV2 has 3 terminals

View File

@ -208,10 +208,13 @@ GDS2Reader::get_string (std::string &s) const
{
if (m_reclen == 0) {
s.clear ();
} else if (mp_rec_buf [m_reclen - 1] != 0) {
s.assign ((const char *) mp_rec_buf, m_reclen);
} else {
s.assign ((const char *) mp_rec_buf, m_reclen - 1);
// strip padding 0 characters
unsigned long n = m_reclen;
while (n > 0 && mp_rec_buf [n - 1] == 0) {
--n;
}
s.assign ((const char *) mp_rec_buf, n);
}
}

View File

@ -685,3 +685,22 @@ TEST(4_CollectModeAdd)
db::compare_layouts (_this, layout, fn_au, db::WriteGDS2, 1);
}
// border case with multiple padding 0 for SNAME and STRING records
TEST(5_issue893)
{
db::Manager m (false);
db::Layout layout (&m);
db::LoadLayoutOptions options;
options.get_options<db::CommonReaderOptions> ().cell_conflict_resolution = db::AddToCell;
{
tl::InputStream file (tl::testdata () + "/gds/issue_893.gds");
db::Reader reader (file);
reader.read (layout, options);
}
std::string fn_au (tl::testdata () + "/gds/issue_893_au.gds");
db::compare_layouts (_this, layout, fn_au, db::WriteGDS2, 1);
}

View File

@ -246,6 +246,7 @@ InputHttpStreamPrivateData::InputHttpStreamPrivateData (const std::string &url)
s_auth_handler = new AuthenticationHandler ();
connect (s_network_manager, SIGNAL (authenticationRequired (QNetworkReply *, QAuthenticator *)), s_auth_handler, SLOT (authenticationRequired (QNetworkReply *, QAuthenticator *)));
connect (s_network_manager, SIGNAL (proxyAuthenticationRequired (const QNetworkProxy &, QAuthenticator *)), s_auth_handler, SLOT (proxyAuthenticationRequired (const QNetworkProxy &, QAuthenticator *)));
connect (s_network_manager, SIGNAL (sslErrors (QNetworkReply *, const QList<QSslError> &)), this, SLOT (sslErrors (QNetworkReply *, const QList<QSslError> &)));
tl::StaticObjects::reg (&s_network_manager);
tl::StaticObjects::reg (&s_auth_handler);
@ -346,6 +347,8 @@ InputHttpStreamPrivateData::issue_request (const QUrl &url)
delete mp_buffer;
mp_buffer = 0;
m_ssl_errors.clear ();
// remove old request (important for redirect)
close ();
@ -462,13 +465,18 @@ InputHttpStreamPrivateData::read (char *b, size_t n)
break;
default:
em = tl::to_string (QObject::tr ("Network API error"));
if (! m_ssl_errors.empty ()) {
em += tl::to_string (QObject::tr (" (with SSL errors: "));
em += m_ssl_errors;
em += ")";
}
}
ec = int (mp_reply->error ());
}
QByteArray data = mp_reply->readAll ();
throw HttpErrorException (em, ec, tl::to_string (mp_reply->url ().toString ()), tl::to_string (data.constData (), (int)data.size ()));
throw HttpErrorException (em, ec, tl::to_string (mp_reply->url ().toString ()), tl::to_string (data.constData (), (int) data.size ()));
}
@ -480,6 +488,20 @@ InputHttpStreamPrivateData::read (char *b, size_t n)
return data.size ();
}
void
InputHttpStreamPrivateData::sslErrors (QNetworkReply *, const QList<QSslError> &errors)
{
// log SSL errors
for (QList<QSslError>::const_iterator e = errors.begin (); e != errors.end (); ++e) {
if (! m_ssl_errors.empty ()) {
m_ssl_errors += ", ";
}
m_ssl_errors += "\"";
m_ssl_errors += tl::to_string (e->errorString ());
m_ssl_errors += "\"";
}
}
void
InputHttpStreamPrivateData::reset ()
{

View File

@ -31,9 +31,9 @@
#include <QBuffer>
#include <QByteArray>
#include <QTimer>
#include <QNetworkAccessManager>
#include <memory>
class QNetworkAccessManager;
class QNetworkReply;
class QNetworkProxy;
class QAuthenticator;
@ -105,6 +105,7 @@ public:
private slots:
void finished (QNetworkReply *);
void resend ();
void sslErrors (QNetworkReply *reply, const QList<QSslError> &errors);
private:
std::string m_url;
@ -116,6 +117,7 @@ private:
std::map<std::string, std::string> m_headers;
tl::Event m_ready;
QTimer *mp_resend_timer;
std::string m_ssl_errors;
void issue_request (const QUrl &url);
};

10
testdata/algo/issue-898.cir vendored Normal file
View File

@ -0,0 +1,10 @@
X0 FILLER_CAP
R$1 vdd gnd 1k
.subckt FILLER_CAP
M0 gnd vdd gnd gnd NMOS W=10u L=10u
.ends FILLER_CAP
.global vdd gnd

View File

@ -22,4 +22,6 @@ h.with_holes(1..3).output(103, 0)
h.with_holes(1..1).output(104, 0)
h.with_holes(2, nil).output(105, 0)
h.with_holes(0, nil).output(106, 0)
h.with_holes.output(107, 0)
h.without_holes.output(108, 0)

Binary file not shown.

Binary file not shown.

BIN
testdata/gds/issue_893.gds vendored Normal file

Binary file not shown.

BIN
testdata/gds/issue_893_au.gds vendored Normal file

Binary file not shown.

View File

@ -167,7 +167,10 @@ proc header { } {
proc tail {} {
global output
record END
puts -nonewline $output [ binary format {x255} ]
# 254-byte padding string (uint 0 written as 0x80 0x80 ... 0x80 0x00)
for { set i 0 } { $i < 253 } { incr i } { byte 128 }
byte 0;
uint 0; # Validation scheme: No validation
}

Binary file not shown.

View File

@ -11,7 +11,7 @@
# </content>
# </test>
header
header
# parts of START record
real 0 1000.0
uint 0 ;# offset table is in start record

Binary file not shown.

View File

@ -10,7 +10,7 @@
# </content>
# </test>
header
header
# parts of START record
real 2 0.5
uint 0 ;# offset table is in start record

Binary file not shown.

View File

@ -10,7 +10,7 @@
# </content>
# </test>
header
header
# parts of START record
real 4 10.0 4.0
uint 0 ;# offset table is in start record

Binary file not shown.

View File

@ -10,7 +10,7 @@
# </content>
# </test>
header
header
# parts of START record
real 6 12.5
uint 0 ;# offset table is in start record

Binary file not shown.

View File

@ -11,7 +11,7 @@
# </test>
header
header
# parts of START record
real 7 12.5
uint 0 ;# offset table is in start record

Binary file not shown.

View File

@ -37,14 +37,14 @@
# </content>
# </test>
header
header
real 0 1000.0
uint 0 ;# offset table is in start record
for { set i 0 } { $i < 12 } { incr i } { uint 0 }
# Cell A
record CELL_STR
str A
str A
record RECTANGLE
bits 01100011 ;# SWHXYRDL
@ -93,7 +93,7 @@ record TEXT
# Cell B
record CELL_STR
str B
str B
record RECTANGLE
bits 01100011 ;# SWHXYRDL
@ -128,7 +128,7 @@ record TEXT
int 200 ;# text-x (abs)
int 200 ;# text-y (abs)
record XYRELATIVE
record XYRELATIVE
record RECTANGLE
bits 00011000 ;# SWHXYRDL
@ -146,12 +146,12 @@ uint 17 ;# PLACEMENT (no mag, manhattan angles)
uint 17 ;# PLACEMENT (no mag, manhattan angles)
bits 00110000 ;# CNXYRAAF
int 50 ;# placement-x
int 50 ;# placement-y
int 50 ;# placement-x (rel.)
int 50 ;# placement-y (rel.)
# Cell TOP
record CELL_STR
str TOP
str TOP
uint 17 ;# PLACEMENT (no mag, manhattan angles)
bits 10000000 ;# CNXYRAAF

Binary file not shown.

View File

@ -9,7 +9,7 @@
# <test-intention>Property name references by ID</test-intention>
# </test>
header
header
real 0 1000.0
uint 0 ;# offset table is in start record
for { set i 0 } { $i < 12 } { incr i } { uint 0 }
@ -26,15 +26,15 @@ record PROPSTRING_ID
# property name 0
record PROPNAME
str PROP0
str PROP0
# property name 1
record PROPNAME
str PROP1
str PROP1
# Cell A
record CELL_STR
str A
str A
record XYRELATIVE
@ -45,7 +45,7 @@ record RECTANGLE
uint 100 ;# width
uint 200 ;# height
record PROPERTY
record PROPERTY
bits 00000100 ;# property info byte UUUUVCNS
str PROPX
@ -55,12 +55,12 @@ record RECTANGLE
uint 2 ;# datatype
uint 100 ;# width
uint 200 ;# height
int 0
int 1000
int 0 ;# geometry-x (relative)
int 1000 ;# geometry-y (relative)
record PROPERTY
record PROPERTY
bits 00010110 ;# property info byte UUUUVCNS
uint 0
uint 0 ;# propname-id
real 1 -5 ;# prop value #0
record RECTANGLE
@ -69,14 +69,14 @@ record RECTANGLE
uint 2 ;# datatype
uint 100 ;# width
uint 200 ;# height
int 0
int 1000
int 0 ;# geometry-x (relative)
int 1000 ;# geometry-y (relative)
record PROPERTY
record PROPERTY
bits 01000110 ;# property info byte UUUUVCNS
uint 0 ;# propname-id
uint 8 ;# prop-value #0 (unsigned int)
uint 25
uint 25
uint 9 ;# prop-value #1 (signed int)
int -124
uint 10 ;# prop-value #2 (a-string)
@ -90,14 +90,14 @@ record RECTANGLE
uint 2 ;# datatype
uint 100 ;# width
uint 200 ;# height
int 0
int 1000
int 0 ;# geometry-x (relative)
int 1000 ;# geometry-y (relative)
record PROPERTY
record PROPERTY
bits 11110000 ;# property info byte UUUUVCNS
uint 3 ;# number of values
uint 0 ;# prop-value #0 (real as unsigned int)
uint 25
uint 25
uint 9 ;# prop-value #1 (signed int)
int -124
uint 14 ;# prop-value #2 (prop-string reference number)
@ -109,10 +109,10 @@ record RECTANGLE
uint 2 ;# datatype
uint 100 ;# width
uint 200 ;# height
int 0
int 1000
int 0 ;# geometry-x (relative)
int 1000 ;# geometry-y (relative)
record PROPERTY
record PROPERTY
bits 00001000 ;# property info byte UUUUVCNS
record XYABSOLUTE
@ -122,8 +122,8 @@ record TEXT
str A ;# text-string
uint 2 ;# text-layer
uint 1 ;# text-datatype
int 1000
int 0
int 1000 ;# text-x (absolute)
int 0 ;# text-y (absolute)
record PROPERTY_REP
@ -133,15 +133,15 @@ record PATH
uint 2 ;# datatype
uint 10 ;# half-width
bits 00001111 ;# extension-scheme SSEE
int 5
int 5
int -5
uint 0 ;# pointlist: 1-delta (hor. first)
uint 3
uint 3
int 150
int 50
int -50
int 2000 ;# geometry-x
int 0 ;# geometry-y
int 2000 ;# geometry-x (absolute)
int 0 ;# geometry-y (absolute)
record PROPERTY_REP
@ -150,17 +150,17 @@ record POLYGON
uint 1 ;# layer
uint 2 ;# datatype
uint 0 ;# pointlist: 1-delta (hor. first)
uint 4
uint 4
int 150
int 50
int -50
int 50
int 3000 ;# geometry-x
int 0 ;# geometry-y
int 3000 ;# geometry-x (absolute)
int 0 ;# geometry-y (absolute)
record PROPERTY_REP
record PROPERTY
record PROPERTY
bits 00000110 ;# property info byte UUUUVCNS
uint 1 ;# propname-id

Binary file not shown.

View File

@ -9,7 +9,7 @@
# <test-intention>Property name references by ID</test-intention>
# </test>
header
header
real 0 1000.0
uint 0 ;# offset table is in start record
for { set i 0 } { $i < 12 } { incr i } { uint 0 }
@ -26,15 +26,15 @@ record PROPSTRING_ID
# property name 0
record PROPNAME
str PROP0
str PROP0
# property name 1
record PROPNAME
str PROP1
str PROP1
# Cell A
record CELL_STR
str A
str A
record XYRELATIVE
@ -45,12 +45,12 @@ record RECTANGLE
uint 100 ;# width
uint 200 ;# height
uint 1 ;# repetition (3x2 matrix)
uint 1
uint 1
uint 0
uint 300
uint 320
record PROPERTY
record PROPERTY
bits 00000100 ;# property info byte UUUUVCNS
str PROPX
@ -60,13 +60,13 @@ record RECTANGLE
uint 2 ;# datatype
uint 100 ;# width
uint 200 ;# height
int 0
int 1000
int 0 ;# geometry-x (relative)
int 1000 ;# geometry-y (relative)
uint 0 ;# repetition (reuse)
record PROPERTY
record PROPERTY
bits 00010110 ;# property info byte UUUUVCNS
uint 0
uint 0 ;# propname-id
real 1 -5 ;# prop value #0
record RECTANGLE
@ -75,15 +75,15 @@ record RECTANGLE
uint 2 ;# datatype
uint 100 ;# width
uint 200 ;# height
int 0
int 1000
int 0 ;# geometry-x (relative)
int 1000 ;# geometry-y (relative)
uint 0 ;# repetition (reuse)
record PROPERTY
record PROPERTY
bits 01000110 ;# property info byte UUUUVCNS
uint 0 ;# propname-id
uint 8 ;# prop-value #0 (unsigned int)
uint 25
uint 25
uint 9 ;# prop-value #1 (signed int)
int -124
uint 10 ;# prop-value #2 (a-string)
@ -97,15 +97,15 @@ record RECTANGLE
uint 2 ;# datatype
uint 100 ;# width
uint 200 ;# height
int 0
int 1000
int 0 ;# geometry-x (relative)
int 1000 ;# geometry-y (relative)
uint 0 ;# repetition (reuse)
record PROPERTY
record PROPERTY
bits 11110000 ;# property info byte UUUUVCNS
uint 3 ;# number of values
uint 0 ;# prop-value #0 (real as unsigned int)
uint 25
uint 25
uint 9 ;# prop-value #1 (signed int)
int -124
uint 14 ;# prop-value #2 (prop-string reference number)
@ -117,11 +117,11 @@ record RECTANGLE
uint 2 ;# datatype
uint 100 ;# width
uint 200 ;# height
int 0
int 1000
int 0 ;# geometry-x (relative)
int 1000 ;# geometry-y (relative)
uint 0 ;# repetition (reuse)
record PROPERTY
record PROPERTY
bits 00001000 ;# property info byte UUUUVCNS
record XYABSOLUTE
@ -131,8 +131,8 @@ record TEXT
str A ;# text-string
uint 2 ;# text-layer
uint 1 ;# text-datatype
int 1000
int 0
int 1000 ;# text-x (absolute)
int 0 ;# text-y (absolute)
uint 0 ;# repetition (reuse)
record PROPERTY_REP
@ -143,15 +143,15 @@ record PATH
uint 2 ;# datatype
uint 10 ;# half-width
bits 00001111 ;# extension-scheme SSEE
int 5
int 5
int -5
uint 0 ;# pointlist: 1-delta (hor. first)
uint 3
uint 3
int 150
int 50
int -50
int 2000 ;# geometry-x
int 0 ;# geometry-y
int 2000 ;# geometry-x (absolute)
int 0 ;# geometry-y (absolute)
uint 0 ;# repetition (reuse)
record PROPERTY_REP
@ -161,18 +161,18 @@ record POLYGON
uint 1 ;# layer
uint 2 ;# datatype
uint 0 ;# pointlist: 1-delta (hor. first)
uint 4
uint 4
int 150
int 50
int -50
int 50
int 3000 ;# geometry-x
int 0 ;# geometry-y
int 3000 ;# geometry-x (absolute)
int 0 ;# geometry-y (absolute)
uint 0 ;# repetition (reuse)
record PROPERTY_REP
record PROPERTY
record PROPERTY
bits 00000110 ;# property info byte UUUUVCNS
uint 1 ;# propname-id

Binary file not shown.

View File

@ -10,7 +10,7 @@
# <test-intention>Property name references by ID</test-intention>
# </test>
header
header
real 0 1000.0
uint 0 ;# offset table is in start record
for { set i 0 } { $i < 12 } { incr i } { uint 0 }
@ -27,11 +27,11 @@ record PROPSTRING_ID
# property name 0
record PROPNAME
str S_GDS_PROPERTY
str S_GDS_PROPERTY
# Cell A
record CELL_STR
str A
str A
record XYRELATIVE
@ -41,14 +41,14 @@ record RECTANGLE
uint 2 ;# datatype
uint 100 ;# width
uint 200 ;# height
int 0
int 1000
int 0 ;# geometry-x (relative)
int 1000 ;# geometry-y (relative)
record PROPERTY
record PROPERTY
bits 00100111 ;# property info byte UUUUVCNS
uint 0 ;# propname-id
uint 8 ;# prop-value #0 (unsigned int)
uint 25
uint 25
uint 10 ;# prop-value #2 (a-string)
str PROP_VALUE2
@ -58,14 +58,14 @@ record RECTANGLE
uint 2 ;# datatype
uint 100 ;# width
uint 200 ;# height
int 0
int 1000
int 0 ;# geometry-x (relative)
int 1000 ;# geometry-y (relative)
record PROPERTY
record PROPERTY
bits 11110001 ;# property info byte UUUUVCNS
uint 2 ;# number of values
uint 8 ;# prop-value #0 (unsigned int)
uint 10
uint 10
uint 14 ;# prop-value #2 (prop-string reference number)
uint 13
@ -75,10 +75,10 @@ record RECTANGLE
uint 2 ;# datatype
uint 100 ;# width
uint 200 ;# height
int 0
int 1000
int 0 ;# geometry-x (relative)
int 1000 ;# geometry-y (relative)
record PROPERTY
record PROPERTY
bits 00001001 ;# property info byte UUUUVCNS
record RECTANGLE
@ -87,10 +87,10 @@ record RECTANGLE
uint 2 ;# datatype
uint 100 ;# width
uint 200 ;# height
int 0
int 1000
int 0 ;# geometry-x (relative)
int 1000 ;# geometry-y (relative)
record PROPERTY_REP
record PROPERTY_REP
record RECTANGLE
bits 01111011 ;# SWHXYRDL
@ -98,17 +98,17 @@ record RECTANGLE
uint 2 ;# datatype
uint 100 ;# width
uint 200 ;# height
int 0
int 1000
int 0 ;# geometry-x (relative)
int 1000 ;# geometry-y (relative)
record PROPERTY
record PROPERTY
bits 00001001 ;# property info byte UUUUVCNS
record PROPERTY
record PROPERTY
bits 00100111 ;# property info byte UUUUVCNS
uint 0 ;# propname-id
uint 8 ;# prop-value #0 (unsigned int)
uint 25
uint 25
uint 10 ;# prop-value #2 (a-string)
str PROP_VALUE2
@ -119,8 +119,8 @@ record TEXT
str A ;# text-string
uint 2 ;# text-layer
uint 1 ;# text-datatype
int 1000
int 0
int 1000 ;# text-x (absolute)
int 0 ;# text-y (absolute)
record PROPERTY_REP
@ -130,15 +130,15 @@ record PATH
uint 2 ;# datatype
uint 10 ;# half-width
bits 00001111 ;# extension-scheme SSEE
int 5
int 5
int -5
uint 0 ;# pointlist: 1-delta (hor. first)
uint 3
uint 3
int 150
int 50
int -50
int 2000 ;# geometry-x
int 0 ;# geometry-y
int 2000 ;# geometry-x (absolute)
int 0 ;# geometry-y (absolute)
record PROPERTY_REP
@ -147,13 +147,13 @@ record POLYGON
uint 1 ;# layer
uint 2 ;# datatype
uint 0 ;# pointlist: 1-delta (hor. first)
uint 4
uint 4
int 150
int 50
int -50
int 50
int 3000 ;# geometry-x
int 0 ;# geometry-y
int 3000 ;# geometry-x (absolute)
int 0 ;# geometry-y (absolute)
record PROPERTY_REP

Binary file not shown.

View File

@ -10,7 +10,7 @@
# <test-intention>Instances with properties</test-intention>
# </test>
header
header
real 0 1000.0
uint 0 ;# offset table is in start record
for { set i 0 } { $i < 12 } { incr i } { uint 0 }
@ -27,11 +27,11 @@ record PROPSTRING_ID
# property name 0
record PROPNAME
str S_GDS_PROPERTY
str S_GDS_PROPERTY
# Cell A
record CELL_STR
str A
str A
record RECTANGLE
bits 01111011 ;# SWHXYRDL
@ -44,75 +44,75 @@ record RECTANGLE
# Cell TOP
record CELL_STR
str TOP
str TOP
uint 17 ;# PLACEMENT (no mag, manhattan angles)
bits 10110000 ;# CNXYRAAF
str A
int -300 ;# placement-x
int 400 ;# placement-y
int -300 ;# placement-x (absolute)
int 400 ;# placement-y (absolute)
record PROPERTY
record PROPERTY
bits 00100111 ;# property info byte UUUUVCNS
uint 0 ;# propname-id
uint 8 ;# prop-value #0 (unsigned int)
uint 25
uint 25
uint 10 ;# prop-value #2 (a-string)
str PROP_VALUE2
uint 17 ;# PLACEMENT (no mag, manhattan angles)
bits 00110000 ;# CNXYRAAF
int 0 ;# placement-x
int 200 ;# placement-y
int 0 ;# placement-x (absolute)
int 200 ;# placement-y (absolute)
record PROPERTY
record PROPERTY
bits 11110001 ;# property info byte UUUUVCNS
uint 2 ;# number of values
uint 8 ;# prop-value #0 (unsigned int)
uint 10
uint 10
uint 14 ;# prop-value #2 (prop-string reference number)
uint 13
uint 17 ;# PLACEMENT (no mag, manhattan angles)
bits 00010000 ;# CNXYRAAF
int 400 ;# placement-y
int 400 ;# placement-y (absolute)
record PROPERTY
record PROPERTY
bits 00001001 ;# property info byte UUUUVCNS
uint 17 ;# PLACEMENT (no mag, manhattan angles)
bits 00100000 ;# CNXYRAAF
int 300 ;# placement-x
int 300 ;# placement-x (absolute)
record PROPERTY_REP
record PROPERTY_REP
record XYABSOLUTE
uint 17 ;# PLACEMENT (no mag, manhattan angles)
bits 00110001 ;# CNXYRAAF
int 700 ;# placement-x
int 400 ;# placement-y
int 700 ;# placement-x (absolute)
int 400 ;# placement-y (absolute)
record PROPERTY
record PROPERTY
bits 00001001 ;# property info byte UUUUVCNS
record XYRELATIVE
uint 17 ;# PLACEMENT (no mag, manhattan angles)
bits 00010010 ;# CNXYRAAF
int 1000 ;# placement-y
int 1000 ;# placement-y (relative)
record PROPERTY
record PROPERTY
bits 00100111 ;# property info byte UUUUVCNS
uint 0 ;# propname-id
uint 8 ;# prop-value #0 (unsigned int)
uint 25
uint 25
uint 10 ;# prop-value #2 (a-string)
str PROP_VALUE2
uint 17 ;# PLACEMENT (no mag, manhattan angles)
bits 00010011 ;# CNXYRAAF
int 1000 ;# placement-y
int 1000 ;# placement-y (relative)
record PROPERTY_REP
@ -120,10 +120,10 @@ record XYABSOLUTE
uint 17 ;# PLACEMENT (no mag, manhattan angles)
bits 00111111 ;# CNXYRAAF
int 2000 ;# placement-x
int 0 ;# placement-y
int 2000 ;# placement-x (absolute)
int 0 ;# placement-y (absolute)
uint 1 ;# repetition (3x4 matrix)
uint 1
uint 1
uint 2
uint 300
uint 300
@ -134,38 +134,38 @@ record XYRELATIVE
uint 17 ;# PLACEMENT (no mag, manhattan angles)
bits 00111111 ;# CNXYRAAF
int 2000 ;# placement-x
int 0 ;# placement-y
int 2000 ;# placement-x (relative)
int 0 ;# placement-y (relative)
uint 0 ;# repetition (reuse)
record PROPERTY_REP
uint 17 ;# PLACEMENT (no mag, manhattan angles)
bits 00111111 ;# CNXYRAAF
int 2000 ;# placement-x
int 0 ;# placement-y
int 2000 ;# placement-x (relative)
int 0 ;# placement-y (relative)
uint 2 ;# repetition (3 columns)
uint 1
uint 1
uint 320
record PROPERTY_REP
uint 17 ;# PLACEMENT (no mag, manhattan angles)
bits 00111111 ;# CNXYRAAF
int 2000 ;# placement-x
int 0 ;# placement-y
int 2000 ;# placement-x (relative)
int 0 ;# placement-y (relative)
uint 3 ;# repetition (4 columns)
uint 2
uint 2
uint 310
record PROPERTY_REP
uint 17 ;# PLACEMENT (no mag, manhattan angles)
bits 00111111 ;# CNXYRAAF
int 2000 ;# placement-x
int 0 ;# placement-y
int 2000 ;# placement-x (relative)
int 0 ;# placement-y (relative)
uint 4 ;# repetition (4 columns, arbitrary spacing)
uint 2
uint 2
uint 320
uint 330
uint 340
@ -174,12 +174,12 @@ record PROPERTY_REP
uint 17 ;# PLACEMENT (no mag, manhattan angles)
bits 00111111 ;# CNXYRAAF
int 2000 ;# placement-x
int 0 ;# placement-y
int 2000 ;# placement-x (relative)
int 0 ;# placement-y (relative)
uint 8 ;# repetition (3x4 matrix, arbitrary displacement vectors)
uint 1 ;# n-dimension
uint 2 ;# m-dimension
uint [ expr 4*310+1 ] ;# n-displacement (g-delta: 310,320)
uint 1 ;# n-dimension
uint 2 ;# m-dimension
uint [ expr 4*310+1 ] ;# n-displacement (g-delta: 310,320)
int 320
uint [ expr 16*330+10 ] ;# n-displacement (g-delta: 330-northwest=-330,330)

Binary file not shown.

View File

@ -10,14 +10,14 @@
# <test-intention>Forward references</test-intention>
# </test>
header
header
real 0 1000.0
uint 0 ;# offset table is in start record
for { set i 0 } { $i < 12 } { incr i } { uint 0 }
# Cell A
record CELL_STR
str A
str A
record XYRELATIVE
@ -28,12 +28,12 @@ record RECTANGLE
uint 100 ;# width
uint 200 ;# height
uint 1 ;# repetition (3x2 matrix)
uint 1
uint 1
uint 0
uint 300
uint 320
record PROPERTY
record PROPERTY
bits 00000100 ;# property info byte UUUUVCNS
str PROPX
@ -43,13 +43,13 @@ record RECTANGLE
uint 2 ;# datatype
uint 100 ;# width
uint 200 ;# height
int 0
int 1000
int 0 ;# geometry-x (relative)
int 1000 ;# geometry-y (relative)
uint 0 ;# repetition (reuse)
record PROPERTY
record PROPERTY
bits 00010110 ;# property info byte UUUUVCNS
uint 0
uint 0 ;# propname-id
real 1 -5 ;# prop value #0
record RECTANGLE
@ -58,15 +58,15 @@ record RECTANGLE
uint 2 ;# datatype
uint 100 ;# width
uint 200 ;# height
int 0
int 1000
int 0 ;# geometry-x (relative)
int 1000 ;# geometry-y (relative)
uint 0 ;# repetition (reuse)
record PROPERTY
record PROPERTY
bits 01000110 ;# property info byte UUUUVCNS
uint 0 ;# propname-id
uint 8 ;# prop-value #0 (unsigned int)
uint 25
uint 25
uint 9 ;# prop-value #1 (signed int)
int -124
uint 10 ;# prop-value #2 (a-string)
@ -80,15 +80,15 @@ record RECTANGLE
uint 2 ;# datatype
uint 100 ;# width
uint 200 ;# height
int 0
int 1000
int 0 ;# geometry-x (relative)
int 1000 ;# geometry-y (relative)
uint 0 ;# repetition (reuse)
record PROPERTY
record PROPERTY
bits 11110000 ;# property info byte UUUUVCNS
uint 3 ;# number of values
uint 0 ;# prop-value #0 (real as unsigned int)
uint 25
uint 25
uint 9 ;# prop-value #1 (signed int)
int -124
uint 14 ;# prop-value #2 (prop-string reference number)
@ -100,11 +100,11 @@ record RECTANGLE
uint 2 ;# datatype
uint 100 ;# width
uint 200 ;# height
int 0
int 1000
int 0 ;# geometry-x (relative)
int 1000 ;# geometry-y (relative)
uint 0 ;# repetition (reuse)
record PROPERTY
record PROPERTY
bits 00001000 ;# property info byte UUUUVCNS
record XYABSOLUTE
@ -114,8 +114,8 @@ record TEXT
str A ;# text-string
uint 2 ;# text-layer
uint 1 ;# text-datatype
int 1000
int 0
int 1000 ;# text-x (absolute)
int 0 ;# text-y (absolute)
uint 0 ;# repetition (reuse)
record PROPERTY_REP
@ -126,15 +126,15 @@ record PATH
uint 2 ;# datatype
uint 10 ;# half-width
bits 00001111 ;# extension-scheme SSEE
int 5
int 5
int -5
uint 0 ;# pointlist: 1-delta (hor. first)
uint 3
uint 3
int 150
int 50
int -50
int 2000 ;# geometry-x
int 0 ;# geometry-y
int 2000 ;# geometry-x (absolute)
int 0 ;# geometry-y (absolute)
uint 0 ;# repetition (reuse)
record PROPERTY_REP
@ -144,18 +144,18 @@ record POLYGON
uint 1 ;# layer
uint 2 ;# datatype
uint 0 ;# pointlist: 1-delta (hor. first)
uint 4
uint 4
int 150
int 50
int -50
int 50
int 3000 ;# geometry-x
int 0 ;# geometry-y
int 3000 ;# geometry-x (absolute)
int 0 ;# geometry-y (absolute)
uint 0 ;# repetition (reuse)
record PROPERTY_REP
record PROPERTY
record PROPERTY
bits 00000110 ;# property info byte UUUUVCNS
uint 1 ;# propname-id
@ -171,11 +171,11 @@ record PROPSTRING_ID
# property name 0
record PROPNAME
str PROP0
str PROP0
# property name 1
record PROPNAME
str PROP1
str PROP1
tail

Binary file not shown.

View File

@ -10,7 +10,7 @@
# <test-intention>Instances with properties</test-intention>
# </test>
header
header
real 0 1000.0
uint 0 ;# offset table is in start record
for { set i 0 } { $i < 12 } { incr i } { uint 0 }
@ -27,7 +27,7 @@ record PROPSTRING_ID
# Cell A
record CELL_STR
str A
str A
record RECTANGLE
bits 01111011 ;# SWHXYRDL
@ -40,83 +40,83 @@ record RECTANGLE
# Cell TOP
record CELL_STR
str TOP
str TOP
uint 17 ;# PLACEMENT (no mag, manhattan angles)
bits 10110000 ;# CNXYRAAF
str A
int -300 ;# placement-x
int 400 ;# placement-y
int -300 ;# placement-x (absolute)
int 400 ;# placement-y (absolute)
record PROPERTY
record PROPERTY
bits 00100111 ;# property info byte UUUUVCNS
uint 0 ;# propname-id
uint 8 ;# prop-value #0 (unsigned int)
uint 25
uint 25
uint 10 ;# prop-value #2 (a-string)
str PROP_VALUE2
record PROPERTY
record PROPERTY
bits 00100111 ;# property info byte UUUUVCNS
uint 0 ;# propname-id
uint 8 ;# prop-value #0 (unsigned int)
uint 26
uint 26
uint 10 ;# prop-value #2 (a-string)
str PROP_VALUE26
uint 17 ;# PLACEMENT (no mag, manhattan angles)
bits 00110000 ;# CNXYRAAF
int 0 ;# placement-x
int 400 ;# placement-y
int 0 ;# placement-x (absolute)
int 400 ;# placement-y (absolute)
record PROPERTY
record PROPERTY
bits 11110001 ;# property info byte UUUUVCNS
uint 2 ;# number of values
uint 8 ;# prop-value #0 (unsigned int)
uint 10
uint 10
uint 14 ;# prop-value #2 (prop-string reference number)
uint 13
uint 17 ;# PLACEMENT (no mag, manhattan angles)
bits 00010000 ;# CNXYRAAF
int 400 ;# placement-y
int 400 ;# placement-y (absolute)
record PROPERTY
record PROPERTY
bits 00001001 ;# property info byte UUUUVCNS
uint 17 ;# PLACEMENT (no mag, manhattan angles)
bits 00100000 ;# CNXYRAAF
int 300 ;# placement-x
int 300 ;# placement-x (absolute)
record PROPERTY_REP
record PROPERTY_REP
record XYABSOLUTE
uint 17 ;# PLACEMENT (no mag, manhattan angles)
bits 00110001 ;# CNXYRAAF
int 700 ;# placement-x
int 400 ;# placement-y
int 700 ;# placement-x (absolute)
int 400 ;# placement-y (absolute)
record PROPERTY
record PROPERTY
bits 00001001 ;# property info byte UUUUVCNS
record XYRELATIVE
uint 17 ;# PLACEMENT (no mag, manhattan angles)
bits 00010010 ;# CNXYRAAF
int 1000 ;# placement-y
int 1000 ;# placement-y (relative)
record PROPERTY
record PROPERTY
bits 00100111 ;# property info byte UUUUVCNS
uint 0 ;# propname-id
uint 8 ;# prop-value #0 (unsigned int)
uint 25
uint 25
uint 10 ;# prop-value #2 (a-string)
str PROP_VALUE2
uint 17 ;# PLACEMENT (no mag, manhattan angles)
bits 00010011 ;# CNXYRAAF
int 1000 ;# placement-y
int 1000 ;# placement-y (relative)
record PROPERTY_REP
@ -124,10 +124,10 @@ record XYABSOLUTE
uint 17 ;# PLACEMENT (no mag, manhattan angles)
bits 00111111 ;# CNXYRAAF
int 2000 ;# placement-x
int 0 ;# placement-y
int 2000 ;# placement-x (absolute)
int 0 ;# placement-y (absolute)
uint 1 ;# repetition (3x4 matrix)
uint 1
uint 1
uint 2
uint 300
uint 300
@ -138,38 +138,38 @@ record XYRELATIVE
uint 17 ;# PLACEMENT (no mag, manhattan angles)
bits 00111111 ;# CNXYRAAF
int 2000 ;# placement-x
int 0 ;# placement-y
int 2000 ;# placement-x (relative)
int 0 ;# placement-y (relative)
uint 0 ;# repetition (reuse)
record PROPERTY_REP
uint 17 ;# PLACEMENT (no mag, manhattan angles)
bits 00111111 ;# CNXYRAAF
int 2000 ;# placement-x
int 0 ;# placement-y
int 2000 ;# placement-x (relative)
int 0 ;# placement-y (relative)
uint 2 ;# repetition (3 columns)
uint 1
uint 1
uint 320
record PROPERTY_REP
uint 17 ;# PLACEMENT (no mag, manhattan angles)
bits 00111111 ;# CNXYRAAF
int 2000 ;# placement-x
int 0 ;# placement-y
int 2000 ;# placement-x (relative)
int 0 ;# placement-y (relative)
uint 3 ;# repetition (4 columns)
uint 2
uint 2
uint 310
record PROPERTY_REP
uint 17 ;# PLACEMENT (no mag, manhattan angles)
bits 00111111 ;# CNXYRAAF
int 2000 ;# placement-x
int 0 ;# placement-y
int 2000 ;# placement-x (relative)
int 0 ;# placement-y (relative)
uint 4 ;# repetition (4 columns, arbitrary spacing)
uint 2
uint 2
uint 320
uint 330
uint 340
@ -178,12 +178,12 @@ record PROPERTY_REP
uint 17 ;# PLACEMENT (no mag, manhattan angles)
bits 00111111 ;# CNXYRAAF
int 2000 ;# placement-x
int 0 ;# placement-y
int 2000 ;# placement-x (relative)
int 0 ;# placement-y (relative)
uint 8 ;# repetition (3x4 matrix, arbitrary displacement vectors)
uint 1 ;# n-dimension
uint 2 ;# m-dimension
uint [ expr 4*310+1 ] ;# n-displacement (g-delta: 310,320)
uint 1 ;# n-dimension
uint 2 ;# m-dimension
uint [ expr 4*310+1 ] ;# n-displacement (g-delta: 310,320)
int 320
uint [ expr 16*330+10 ] ;# n-displacement (g-delta: 330-northwest=-330,330)
@ -191,7 +191,7 @@ record PROPERTY_REP
# property name 0
record PROPNAME
str S_GDS_PROPERTY
str S_GDS_PROPERTY
tail

Binary file not shown.

View File

@ -3,7 +3,7 @@
# <content-description>File-Level properties</content-description>
# </test>
header
header
real 0 1000.0
uint 0 ;# offset table is in start record
for { set i 0 } { $i < 12 } { incr i } { uint 0 }
@ -30,7 +30,7 @@ record PROPERTY
bits 00010110 ;# UUUUVCNS
uint 13
uint 8 ;# prop-value #0 (unsigned int)
uint 17
uint 17
# property string 12
record PROPSTRING_ID
@ -42,10 +42,10 @@ record PROPERTY
bits 00010110 ;# UUUUVCNS
uint 13
uint 8 ;# prop-value #0 (unsigned int)
uint 42
uint 42
# A cellname records
record CELLNAME
record CELLNAME
str A
# property associated with cell A through CELLNAME
@ -64,7 +64,7 @@ record PROPERTY
bits 00010100 ;# UUUUVCNS
str CellProp1
uint 10 ;# prop-value #0 (string)
str CPValue
str CPValue
# property associated with cell A
record PROPERTY

Binary file not shown.

View File

@ -4,7 +4,7 @@
# <test-intention>Errors on unset modal variables</test-intention>
# </test>
header
header
real 0 1000.0
uint 0 ;# offset table is in start record
for { set i 0 } { $i < 12 } { incr i } { uint 0 }
@ -42,10 +42,10 @@ record PROPERTY
bits 00010110 ;# UUUUVCNS
uint 13
uint 8 ;# prop-value #0 (unsigned int)
uint 42
uint 42
# A cellname records
record CELLNAME
record CELLNAME
str A
# property associated with cell A through CELLNAME
@ -64,7 +64,7 @@ record PROPERTY
bits 00010100 ;# UUUUVCNS
str CellProp1
uint 10 ;# prop-value #0 (string)
str CPValue
str CPValue
# property associated with cell A
record PROPERTY

Binary file not shown.

View File

@ -3,7 +3,7 @@
# <content-description>File-Level properties</content-description>
# </test>
header
header
real 0 1000.0
uint 0 ;# offset table is in start record
for { set i 0 } { $i < 12 } { incr i } { uint 0 }
@ -30,7 +30,7 @@ record PROPERTY
bits 00010110 ;# UUUUVCNS
uint 13
uint 8 ;# prop-value #0 (unsigned int)
uint 17
uint 17
# property string 12
record PROPSTRING_ID
@ -44,7 +44,7 @@ record PROPERTY
uint 13
# A cellname records
record CELLNAME
record CELLNAME
str A
# property associated with cell A through CELLNAME
@ -63,7 +63,7 @@ record PROPERTY
bits 00010100 ;# UUUUVCNS
str CellProp1
uint 10 ;# prop-value #0 (string)
str CPValue
str CPValue
# property associated with cell A
record PROPERTY

Binary file not shown.

View File

@ -7,14 +7,14 @@
# <test-intention>Circle-related modal variables</test-intention>
# </test>
header
header
real 0 1000.0
uint 0 ;# offset table is in start record
for { set i 0 } { $i < 12 } { incr i } { uint 0 }
# Cell A
record CELL_STR
str A
str A
record CIRCLE
bits 00111011 ;# 00rXYRDL
@ -55,7 +55,7 @@ record CIRCLE
uint 100 ;# radius
int 400 ;# geometry-y (relative)
uint 1 ;# repetition (3x4 matrix)
uint 1
uint 1
uint 2
uint 400
uint 300

Binary file not shown.

View File

@ -6,7 +6,7 @@
# <test-intention>Mapping of layer and datatype ranges to names</test-intention>
# </test>
header
header
real 0 1000.0
uint 0 ;# offset table is in start record
for { set i 0 } { $i < 12 } { incr i } { uint 0 }
@ -31,7 +31,7 @@ record LAYERNAME
record LAYERNAME
str E5A
uint 3 ;# layer 5
uint 3 ;# layer 5
uint 5
uint 0 ;# all datatypes
@ -60,7 +60,7 @@ record LAYERNAME
str E5E4
uint 3 ;# layer 5 to 5
uint 5
uint 3 ;# datatype 4
uint 3 ;# datatype 4
uint 4
record LAYERNAME
@ -73,7 +73,7 @@ record LAYERNAME
# Cell A
record CELL_STR
str A
str A
record CIRCLE
bits 00111011 ;# 00rXYRDL

Binary file not shown.

View File

@ -6,7 +6,7 @@
# <test-intention>Mapping of textlayer and texttype ranges to names</test-intention>
# </test>
header
header
real 0 1000.0
uint 0 ;# offset table is in start record
for { set i 0 } { $i < 12 } { incr i } { uint 0 }
@ -31,7 +31,7 @@ record LAYERNAME_TXT
record LAYERNAME_TXT
str E5A
uint 3 ;# layer 5
uint 3 ;# layer 5
uint 5
uint 0 ;# all datatypes
@ -44,7 +44,7 @@ record LAYERNAME_TXT
# Cell A
record CELL_STR
str A
str A
record TEXT
bits 01011011 ;# 0CNXYRTL

Binary file not shown.

View File

@ -6,7 +6,7 @@
# <test-intention>Mapping of layer and datatype ranges to names, mapping of textlayer and texttype ranges to names in the same context but to different names</test-intention>
# </test>
header
header
real 0 1000.0
uint 0 ;# offset table is in start record
for { set i 0 } { $i < 12 } { incr i } { uint 0 }
@ -31,7 +31,7 @@ record LAYERNAME_TXT
record LAYERNAME_TXT
str TE5A
uint 3 ;# layer 5
uint 3 ;# layer 5
uint 5
uint 0 ;# all datatypes
@ -62,7 +62,7 @@ record LAYERNAME
record LAYERNAME
str E5A
uint 3 ;# layer 5
uint 3 ;# layer 5
uint 5
uint 0 ;# all datatypes
@ -75,7 +75,7 @@ record LAYERNAME
# Cell A
record CELL_STR
str A
str A
record TEXT
bits 01011011 ;# 0CNXYRTL

Binary file not shown.

View File

@ -7,14 +7,14 @@
# <test-intention>Mapping of layer and datatype ranges to names, mapping of textlayer and texttype ranges to names in the same context but to different names</test-intention>
# </test>
header
header
real 0 1000.0
uint 0 ;# offset table is in start record
for { set i 0 } { $i < 12 } { incr i } { uint 0 }
# Cell A
record CELL_STR
str A
str A
record TEXT
bits 01011011 ;# 0CNXYRTL
@ -292,7 +292,7 @@ record LAYERNAME_TXT
record LAYERNAME_TXT
str TE5A
uint 3 ;# layer 5
uint 3 ;# layer 5
uint 5
uint 0 ;# all datatypes
@ -323,7 +323,7 @@ record LAYERNAME
record LAYERNAME
str E5A
uint 3 ;# layer 5
uint 3 ;# layer 5
uint 5
uint 0 ;# all datatypes

Binary file not shown.

View File

@ -21,14 +21,14 @@
# </content>
# </test>
header
header
real 0 1000.0
uint 0 ;# offset table is in start record
for { set i 0 } { $i < 12 } { incr i } { uint 0 }
# Cell A
record CELL_STR
str ABCDH
str ABCDH
set cblock_bytes {
22 00 b0 02 b2 02 13
@ -40,8 +40,8 @@ set cblock_bytes {
04 ae 65 3f 12 04 24 36 0b 8b 2c f2 e9 14 16 3d
c6 73 92 4d 64 21 e3 0b 9e cf 9a 15 4f 59 6f 08
83 cc 5d c8 f8 91 7b 25 7f ea 4e e6 03 3c 5b a4
66 88 01 85 d8 37 b2 fc 64 bd c8 25 5a 79 92 b1
99 4b a3 93 65 26 7b 33 bf e6 69 b6 39 7c a9 4b
66 88 01 85 d8 37 b2 fc 64 bd c8 25 5a 79 92 b1
99 4b a3 93 65 26 7b 33 bf e6 69 b6 39 7c a9 4b
40 2e e1 3b 28 a6 79 82 69 41 98 f6 14 ae 60 9b
d7 4c a2 9a 3d 8c 37 f9 6c 03 3f 32 b6 68 2c 64
5c cb f3 9a 49 f3 33 e3 0c a6 dd da 29 2f 98 76

Binary file not shown.

View File

@ -12,7 +12,7 @@
# </content>
# </test>
header
header
real 0 1000.0
uint 0 ;# offset table is in start record
for { set i 0 } { $i < 12 } { incr i } { uint 0 }

Binary file not shown.

View File

@ -16,14 +16,14 @@
# </content>
# </test>
header
header
real 0 1000.0
uint 0 ;# offset table is in start record
for { set i 0 } { $i < 12 } { incr i } { uint 0 }
# XYZ gets assigned 0 implicitly
record CELLNAME
str XYZ
str XYZ
# ABC gets assigned 1 implicitly
record CELLNAME

Binary file not shown.

View File

@ -9,14 +9,14 @@
# <must-fail>Explicit and implicit CELLNAME modes cannot be mixed</must-fail>
# </test>
header
header
real 0 1000.0
uint 0 ;# offset table is in start record
for { set i 0 } { $i < 12 } { incr i } { uint 0 }
# ABC gets assigned 1
# ABC gets assigned 1
record CELLNAME_ID
str ABC
str ABC
uint 1
# XYZ gets assigned 0 implicitly

Binary file not shown.

View File

@ -15,17 +15,17 @@
# </content>
# </test>
header
header
real 0 1000.0
uint 0 ;# offset table is in start record
for { set i 0 } { $i < 12 } { incr i } { uint 0 }
# ABC gets assigned 1
# ABC gets assigned 1
record CELLNAME_ID
str ABC
str ABC
uint 1
# XYZ gets assigned 0
# XYZ gets assigned 0
record CELLNAME_ID
str XYZ
uint 0

Binary file not shown.

View File

@ -9,17 +9,17 @@
# <must-fail>No cellname declared for cell id 2</must-fail>
# </test>
header
header
real 0 1000.0
uint 0 ;# offset table is in start record
for { set i 0 } { $i < 12 } { incr i } { uint 0 }
# ABC gets assigned 1
# ABC gets assigned 1
record CELLNAME_ID
str ABC
str ABC
uint 1
# XYZ gets assigned 0
# XYZ gets assigned 0
record CELLNAME_ID
str XYZ
uint 0

Binary file not shown.

View File

@ -9,17 +9,17 @@
# <must-fail>Invalid n-string</must-fail>
# </test>
header
header
real 0 1000.0
uint 0 ;# offset table is in start record
for { set i 0 } { $i < 12 } { incr i } { uint 0 }
# ABC gets assigned 1
# ABC gets assigned 1
record CELLNAME_ID
str ABC
str ABC
uint 1
# XYZ gets assigned 0
# XYZ gets assigned 0
record CELLNAME_ID
str " XYZ" ;# FAIL: invalid n-string
uint 0

Binary file not shown.

View File

@ -10,17 +10,17 @@
# </content>
# </test>
header
header
real 0 1000.0
uint 0 ;# offset table is in start record
for { set i 0 } { $i < 12 } { incr i } { uint 0 }
# ABC gets assigned 1
# ABC gets assigned 1
record CELLNAME_ID
str ABC
str ABC
uint 1
# XYZ gets assigned 0
# XYZ gets assigned 0
record CELLNAME_ID
str XYZ
uint 0

Binary file not shown.

View File

@ -118,14 +118,14 @@
# </content>
# </test>
header
header
real 0 1000.0
uint 0 ;# offset table is in start record
for { set i 0 } { $i < 12 } { incr i } { uint 0 }
# Cell ABC
record CELL_STR
str ABC
str ABC
record TEXT
bits 01011011 ;# 0CNXYRTL
@ -161,7 +161,7 @@ record TEXT
bits 00001100 ;# 0CNXYRTL
int -200 ;# text-y (relative)
uint 1 ;# repetition (3x4 matrix)
uint 1
uint 1
uint 2
uint 10
uint 12
@ -175,21 +175,21 @@ record TEXT
bits 00001100 ;# 0CNXYRTL
int -200 ;# text-y (relative)
uint 2 ;# repetition (3 columns)
uint 1
uint 1
uint 10
record TEXT
bits 00001100 ;# 0CNXYRTL
int -200 ;# text-y (relative)
uint 3 ;# repetition (4 columns)
uint 2
uint 2
uint 12
record TEXT
bits 00001100 ;# 0CNXYRTL
int -200 ;# text-y (relative)
uint 4 ;# repetition (4 columns, arbitrary spacing)
uint 2
uint 2
uint 12
uint 13
uint 14
@ -198,7 +198,7 @@ record TEXT
bits 00001100 ;# 0CNXYRTL
int -200 ;# text-y (relative)
uint 5 ;# repetition (4 columns, arbitrary spacing, grid 3)
uint 2
uint 2
uint 3
uint 4
uint 5
@ -208,7 +208,7 @@ record TEXT
bits 00001100 ;# 0CNXYRTL
int -200 ;# text-y (relative)
uint 6 ;# repetition (3 columns, arbitrary spacing)
uint 1
uint 1
uint 10
uint 11
@ -216,7 +216,7 @@ record TEXT
bits 00001100 ;# 0CNXYRTL
int -200 ;# text-y (relative)
uint 7 ;# repetition (3 columns, arbitrary spacing, grid 5)
uint 1
uint 1
uint 5
uint 2
uint 3
@ -225,19 +225,19 @@ record TEXT
bits 00001100 ;# 0CNXYRTL
int -200 ;# text-y (relative)
uint 8 ;# repetition (3x4 matrix, arbitrary displacement vectors)
uint 1 ;# n-dimension
uint 2 ;# m-dimension
uint 1 ;# n-dimension
uint 2 ;# m-dimension
uint [ expr 16*10 ] ;# n-displacement (g-delta: 10-east=10,0)
uint [ expr 4*11+3 ] ;# m-displacement (g-delta: -11,-12)
uint [ expr 4*11+3 ] ;# m-displacement (g-delta: -11,-12)
int -12
record TEXT
bits 00001100 ;# 0CNXYRTL
int -200 ;# text-y (relative)
uint 8 ;# repetition (3x4 matrix, arbitrary displacement vectors)
uint 1 ;# n-dimension
uint 2 ;# m-dimension
uint [ expr 4*11+1 ] ;# n-displacement (g-delta: 11,12)
uint 1 ;# n-dimension
uint 2 ;# m-dimension
uint [ expr 4*11+1 ] ;# n-displacement (g-delta: 11,12)
int 12
uint [ expr 16*10+10 ] ;# n-displacement (g-delta: 10-northwest=-10,10)
@ -245,22 +245,22 @@ record TEXT
bits 00001100 ;# 0CNXYRTL
int -200 ;# text-y (relative)
uint 9 ;# repetition (3 times, arbitrary displacement vectors)
uint 1 ;# dimension
uint [ expr 4*11+1 ] ;# n-displacement (g-delta: 11,12)
uint 1 ;# dimension
uint [ expr 4*11+1 ] ;# n-displacement (g-delta: 11,12)
int 12
record TEXT
bits 00001100 ;# 0CNXYRTL
int -200 ;# text-y (relative)
uint 9 ;# repetition (4 times, arbitrary displacement vectors)
uint 2 ;# dimension
uint 2 ;# dimension
uint [ expr 16*10+10 ] ;# n-displacement (g-delta: 10-northwest=-10,10)
record TEXT
bits 00001100 ;# 0CNXYRTL
int -200 ;# text-y (relative)
uint 10 ;# repetition (9 times, once in the middle, others displaced)
uint 7 ;# dimension
uint 7 ;# dimension
uint [ expr 16*10+0 ] ;# n-displacement (g-delta: 10-east=10,0)
uint [ expr 16*10+2 ] ;# n-displacement (g-delta: 10-north=0,10)
uint [ expr 16*10+4 ] ;# n-displacement (g-delta: 10-west=-10,0)
@ -274,8 +274,8 @@ record TEXT
bits 00001100 ;# 0CNXYRTL
int -200 ;# text-y (relative)
uint 10 ;# repetition (3 times, once in the middle, two displaced)
uint 1 ;# dimension
uint [ expr 4*11+3 ] ;# n-displacement (g-delta: -11,12)
uint 1 ;# dimension
uint [ expr 4*11+3 ] ;# n-displacement (g-delta: -11,12)
int 12
uint [ expr 16*10+14 ] ;# n-displacement (g-delta: 10-southeast=10,-10)
@ -298,9 +298,9 @@ record TEXT
bits 00001100 ;# 0CNXYRTL
int -200 ;# text-y (relative)
uint 11 ;# repetition (3 times, once in the middle, two displaced)
uint 1 ;# dimension
uint 1 ;# dimension
uint 3 ;# grid (3)
uint [ expr 4*4+3 ] ;# n-displacement (g-delta: -12,12)
uint [ expr 4*4+3 ] ;# n-displacement (g-delta: -12,12)
int 4
uint [ expr 16*3+14 ] ;# n-displacement (g-delta: 9-southeast=9,-9)

Binary file not shown.

View File

@ -15,7 +15,7 @@
# </content>
# </test>
header
header
real 0 1000.0
uint 0 ;# offset table is in start record
for { set i 0 } { $i < 12 } { incr i } { uint 0 }
@ -23,10 +23,10 @@ header
# Text definition
record TEXTSTRING
str A
# Cell ABC
record CELL_STR
str ABC
str ABC
record TEXT
bits 01110011 ;# 0CNXYRTL
@ -35,5 +35,5 @@ record TEXT
uint 2 ;# text-datatype
int 100 ;# text-x (abs)
tail
tail

Binary file not shown.

View File

@ -7,7 +7,7 @@
# <must-fail>Modal variable accessed before being defined: text-string</must-fail>
# </test>
header
header
real 0 1000.0
uint 0 ;# offset table is in start record
for { set i 0 } { $i < 12 } { incr i } { uint 0 }
@ -15,10 +15,10 @@ header
# Text definition
record TEXTSTRING
str A
# Cell ABC
record CELL_STR
str ABC
str ABC
record TEXT
bits 00011011 ;# 0CNXYRTL
@ -27,5 +27,5 @@ record TEXT
int 100 ;# text-x (abs)
int -200 ;# text-y (abs)
tail
tail

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More