Merge branch 'master' into qtless-canvas

This commit is contained in:
Matthias Koefferlein 2022-05-23 20:42:39 +02:00
commit 3f4fe62dc5
23 changed files with 1377 additions and 496 deletions

View File

@ -205,6 +205,12 @@ while [ "$*" != "" ]; do
-libexpat)
HAVE_EXPAT=1
;;
-qt5)
echo "*** WARNING: -qt5 option is ignored - Qt version is auto-detected now."
;;
-qt4)
echo "*** WARNING: -qt4 option is ignored - Qt version is auto-detected now."
;;
-option)
MAKE_OPT="$MAKE_OPT $1"
shift
@ -243,8 +249,6 @@ while [ "$*" != "" ]; do
echo ""
echo "Special options (usually auto-selected from ruby/python/Qt installation):"
echo ""
echo " -qt4|-qt5 Use Qt4 or Qt5 API [default: auto detect]"
echo ""
echo " -rblib <file> Location of the .so/.dll to link for Ruby support"
echo " -rbinc <dir> Location of the Ruby headers (in particular 'ruby.h')"
echo " -rbinc and -rblib must be set to enable Ruby support"

View File

@ -889,8 +889,8 @@ def Run_Build_Command(parameters):
# (C) Target directories and files
MacBuildDirQAT = parameters['build'] + ".macQAT"
# (D) Qt5
cmd_args += " \\\n -qt5"
# (D) Qt5 | Qt6 (Homebrew)
#cmd_args += " \\\n -qt5" # make 'build.sh' detect the Qt type automatically
cmd_args += " \\\n -qmake %s" % parameters['qmake']
cmd_args += " \\\n -bin %s" % parameters['bin']
cmd_args += " \\\n -build %s" % parameters['build']

View File

@ -272,6 +272,7 @@ module RBA
param_index = @param_decls.length
self.instance_eval("def #{name.to_s}; @param_values[#{param_index}]; end")
self.instance_eval("def set_#{name.to_s}(v); @param_values[#{param_index}] = v; end")
self.instance_eval("def #{name.to_s}=(v); @param_values[#{param_index}] = v; end")
if type == TypeLayer
self.instance_eval("def #{name.to_s}_layer; @layers[#{@layer_param_index.length}]; end")
@layer_param_index.push(param_index)

View File

@ -2423,8 +2423,7 @@ Layout::get_pcell_parameter (cell_index_type cell_index, const std::string &name
if (pcell_variant) {
return pcell_variant->parameter_by_name (name);
} else {
static std::map<std::string, tl::Variant> empty;
return empty;
return tl::Variant ();
}
}
@ -2444,8 +2443,7 @@ Layout::get_named_pcell_parameters (cell_index_type cell_index) const
if (pcell_variant) {
return pcell_variant->parameters_by_name ();
} else {
static std::map<std::string, tl::Variant> empty;
return empty;
return std::map<std::string, tl::Variant> ();
}
}

View File

@ -222,9 +222,19 @@ Library::remap_to (db::Library *other)
} else {
// map pcell parameters by name
std::map<std::string, tl::Variant> param_by_name = lib_pcell->parameters_by_name ();
lp->first->remap (other->get_id (), other->layout ().get_pcell_variant (pn.second, new_pcell_decl->map_parameters (param_by_name)));
db::pcell_parameters_type new_parameters = new_pcell_decl->map_parameters (lib_pcell->parameters_by_name ());
// coerce the new parameters if requested
try {
db::pcell_parameters_type plist = new_parameters;
new_pcell_decl->coerce_parameters (other->layout (), plist);
plist.swap (new_parameters);
} catch (tl::Exception &ex) {
// ignore exception - we will do that again on update() to establish an error message
tl::error << ex.msg ();
}
lp->first->remap (other->get_id (), other->layout ().get_pcell_variant (pn.second, new_parameters));
}

View File

@ -122,13 +122,19 @@ PCellVariant::parameter_by_name (const std::string &name) const
std::map<std::string, tl::Variant>
PCellVariant::parameters_by_name () const
{
return parameters_by_name_from_list (parameters ());
}
std::map<std::string, tl::Variant>
PCellVariant::parameters_by_name_from_list (const db::pcell_parameters_type &list) const
{
std::map<std::string, tl::Variant> param_by_name;
const PCellHeader *header = pcell_header ();
if (header && header->declaration ()) {
db::pcell_parameters_type::const_iterator pp = parameters ().begin ();
db::pcell_parameters_type::const_iterator pp = list.begin ();
const std::vector<db::PCellParameterDeclaration> &pcp = header->declaration ()->parameter_declarations ();
for (std::vector<PCellParameterDeclaration>::const_iterator pd = pcp.begin (); pd != pcp.end () && pp != parameters ().end (); ++pd, ++pp) {
param_by_name.insert (std::make_pair (pd->get_name (), *pp));
@ -155,13 +161,25 @@ PCellVariant::update (ImportLayerMapping *layer_mapping)
std::vector<unsigned int> layer_ids;
try {
layer_ids = header->get_layer_indices (*layout (), m_parameters, layer_mapping);
header->declaration ()->produce (*layout (), layer_ids, m_parameters, *this);
m_display_name = header->declaration ()->get_display_name (m_parameters);
// call coerce prior to produce to make sure we have a validated parameter set
// (note that we cannot persist parameters from here)
db::pcell_parameters_type plist = m_parameters;
header->declaration ()->coerce_parameters (*layout (), plist);
header->declaration ()->produce (*layout (), layer_ids, plist, *this);
m_display_name = header->declaration ()->get_display_name (plist);
} catch (tl::Exception &ex) {
tl::error << ex.msg ();
// put error messages into layout as text objects on error layer
shapes (layout ()->error_layer ()).insert (db::Text (ex.msg (), db::Trans ()));
}
// produce the shape parameters on the guiding shape layer so they can be edited

View File

@ -62,7 +62,12 @@ public:
virtual Cell *clone (Layout &layout) const;
/**
* @brief Get the parameter name map for this variant
* @brief Gets the parameter name map for a parameter list
*/
std::map<std::string, tl::Variant> parameters_by_name_from_list (const pcell_parameters_type &list) const;
/**
* @brief Gets the parameter name map for this variant
*/
std::map<std::string, tl::Variant> parameters_by_name () const;

View File

@ -51,6 +51,7 @@ tl::XMLElementList load_options_xml_element_list ()
tl::XMLElementList save_options_xml_element_list ()
{
tl::XMLElementList elements;
elements.append (tl::make_member (&db::SaveLayoutOptions::format, &db::SaveLayoutOptions::set_format, "format"));
for (tl::Registrar<db::StreamFormatDeclaration>::iterator cls = tl::Registrar<db::StreamFormatDeclaration>::begin (); cls != tl::Registrar<db::StreamFormatDeclaration>::end (); ++cls) {
const StreamFormatDeclaration *decl = dynamic_cast <const StreamFormatDeclaration *> (&*cls);

View File

@ -2048,6 +2048,10 @@ MainWindow::cm_load_layer_props ()
void
MainWindow::load_layer_props_from_file (const std::string &fn)
{
if (! current_view ()) {
throw tl::Exception (tl::to_string (QObject::tr ("No view open to load the layer properties for")));
}
int target_cv_index = -2;
if (current_view ()->cellviews () > 1 && is_single_cv_layer_properties_file (fn)) {
@ -2296,12 +2300,14 @@ MainWindow::do_save (bool as)
db::SaveLayoutOptions options = cv->save_options ();
if (!cv->save_options_valid () && cv->technology ()) {
options = cv->technology ()->save_layout_options ();
options.set_format (cv->save_options ().format ());
}
options.set_dbu (cv->layout ().dbu ());
options.set_format_from_filename (fn);
cv->update_save_options (options);
if (as || options.format ().empty ()) {
options.set_format_from_filename (fn);
}
tl::OutputStream::OutputStreamMode om = tl::OutputStream::OM_Auto;
@ -2338,7 +2344,9 @@ MainWindow::cm_save_all ()
db::SaveLayoutOptions options (cv->save_options ());
options.set_dbu (cv->layout ().dbu ());
options.set_format_from_filename (fn);
if (options.format ().empty ()) {
options.set_format_from_filename (fn);
}
tl::OutputStream::OutputStreamMode om = tl::OutputStream::OM_Auto;

View File

@ -296,7 +296,7 @@ LayoutHandle::update_save_options (db::SaveLayoutOptions &options)
for (tl::Registrar<lay::PluginDeclaration>::iterator cls = tl::Registrar<lay::PluginDeclaration>::begin (); cls != tl::Registrar<lay::PluginDeclaration>::end (); ++cls) {
const lay::StreamWriterPluginDeclaration *decl = dynamic_cast <const lay::StreamWriterPluginDeclaration *> (&*cls);
if (! decl) {
if (! decl || decl->options_alias ()) {
continue;
}
@ -370,6 +370,8 @@ db::LayerMap
LayoutHandle::load (const db::LoadLayoutOptions &options, const std::string &technology)
{
m_load_options = options;
m_save_options = db::SaveLayoutOptions ();
m_save_options_valid = false;
set_tech_name (technology);
@ -389,6 +391,7 @@ LayoutHandle::load (const db::LoadLayoutOptions &options, const std::string &tec
remove_file_from_watcher (filename ());
add_file_to_watcher (filename ());
m_save_options.set_format (reader.format ());
m_dirty = false;
return new_lmap;
}
@ -397,6 +400,8 @@ db::LayerMap
LayoutHandle::load ()
{
m_load_options = db::LoadLayoutOptions ();
m_save_options = db::SaveLayoutOptions ();
m_save_options_valid = false;
set_tech_name (std::string ());
@ -414,6 +419,7 @@ LayoutHandle::load ()
remove_file_from_watcher (filename ());
add_file_to_watcher (filename ());
m_save_options.set_format (reader.format ());
m_dirty = false;
return new_lmap;
}

View File

@ -232,6 +232,14 @@ public:
*/
static const StreamWriterPluginDeclaration *plugin_for_format (const std::string &format_name);
/**
* @brief If the options are shared with another declaration, returns this name of this declaration here
*/
virtual const char *options_alias () const
{
return 0;
}
/**
* @brief Create a format specific options page
*/

View File

@ -683,8 +683,13 @@ StatisticsSource::get (const std::string &url)
<< "<table>" << std::endl
<< "<tr>"
<< "<td>" << tl::to_string (QObject::tr ("Path")) << ":&nbsp;</td><td>" << m_h->filename () << "</td>"
<< "</tr>" << std::endl
<< "<tr>"
<< "</tr>" << std::endl;
if (! m_h->save_options ().format ().empty ()) {
os << "<tr>"
<< "<td>" << tl::to_string (QObject::tr ("Format")) << ":&nbsp;</td><td>" << m_h->save_options ().format () << "</td>"
<< "</tr>" << std::endl;
}
os << "<tr>"
<< "<td>" << tl::to_string (QObject::tr ("Technology")) << ":&nbsp;</td><td>" << m_h->technology ()->description () << format_tech_name (m_h->tech_name ()) << "</td>"
<< "</tr>" << std::endl
<< "<tr>"

View File

@ -339,16 +339,47 @@ SaveLayoutAsOptionsDialog::SaveLayoutAsOptionsDialog (QWidget *parent, const std
fmt_cbx->addItem (tl::to_qstring (fmt->format_title ()));
StreamWriterOptionsPage *page = 0;
// obtain the config page from the plugin which we identify by format name
const StreamWriterPluginDeclaration *decl = plugin_for_format (fmt->format_name ());
if (decl) {
page = decl->format_specific_options_page (options_stack);
}
m_pages.push_back (std::make_pair (page, fmt->format_name ()));
m_tab_positions.push_back (page ? options_stack->addWidget (page) : empty_widget_index);
if (decl) {
const char *alias = decl->options_alias ();
if (alias) {
// alias needs to come before
int index = -1;
int n = 0;
for (tl::Registrar<db::StreamFormatDeclaration>::iterator i = tl::Registrar<db::StreamFormatDeclaration>::begin (); i != tl::Registrar<db::StreamFormatDeclaration>::end (); ++i) {
if (i->format_name () == alias) {
index = n;
}
++n;
}
if (index >= 0 && index < int (m_tab_positions.size ())) {
m_pages.push_back (std::make_pair (m_pages [index].first, fmt->format_name ()));
m_tab_positions.push_back (m_tab_positions[index]);
} else {
m_pages.push_back (std::make_pair ((StreamWriterOptionsPage *) 0, fmt->format_name ()));
m_tab_positions.push_back (empty_widget_index);
}
} else {
StreamWriterOptionsPage *page = decl->format_specific_options_page (options_stack);
m_pages.push_back (std::make_pair (page, fmt->format_name ()));
m_tab_positions.push_back (page ? options_stack->addWidget (page) : empty_widget_index);
}
} else {
m_pages.push_back (std::make_pair ((StreamWriterOptionsPage *) 0, fmt->format_name ()));
m_tab_positions.push_back (empty_widget_index);
}
}
@ -441,7 +472,7 @@ SaveLayoutAsOptionsDialog::get_options (lay::LayoutViewBase *view, unsigned int
for (std::vector< std::pair<StreamWriterOptionsPage *, std::string> >::iterator page = m_pages.begin (); page != m_pages.end (); ++page) {
const StreamWriterPluginDeclaration *decl = plugin_for_format (page->second);
if (decl) {
if (decl && ! decl->options_alias ()) {
std::unique_ptr<db::FormatSpecificWriterOptions> specific_options;
if (options.get_options (page->second)) {

View File

@ -72,40 +72,40 @@ BasicArc::coerce_parameters (const db::Layout & /*layout*/, db::pcell_parameters
return;
}
double ru1 = parameters [p_actual_radius1].to_double ();
double r1 = parameters [p_radius1].to_double ();
double ru1 = parameters [p_radius1].to_double ();
double r1 = parameters [p_actual_radius1].to_double ();
double rs1 = ru1;
if (parameters [p_handle1].is_user <db::DPoint> ()) {
rs1 = parameters [p_handle1].to_user <db::DPoint> ().distance ();
if (parameters [p_actual_handle1].is_user <db::DPoint> ()) {
rs1 = parameters [p_actual_handle1].to_user <db::DPoint> ().distance ();
}
double ru2 = parameters [p_actual_radius2].to_double ();
double r2 = parameters [p_radius2].to_double ();
double ru2 = parameters [p_radius2].to_double ();
double r2 = parameters [p_actual_radius2].to_double ();
double rs2 = ru2;
if (parameters [p_handle2].is_user <db::DPoint> ()) {
rs2 = parameters [p_handle2].to_user <db::DPoint> ().distance ();
if (parameters [p_actual_handle2].is_user <db::DPoint> ()) {
rs2 = parameters [p_actual_handle2].to_user <db::DPoint> ().distance ();
}
double a1u = parameters [p_actual_start_angle].to_double ();
double a1 = parameters [p_start_angle].to_double ();
double a1u = parameters [p_start_angle].to_double ();
double a1 = parameters [p_actual_start_angle].to_double ();
db::DPoint h1u;
if (parameters [p_actual_handle1].is_user<db::DPoint> ()) {
h1u = parameters [p_actual_handle1].to_user<db::DPoint> ();
if (parameters [p_handle1].is_user<db::DPoint> ()) {
h1u = parameters [p_handle1].to_user<db::DPoint> ();
}
db::DPoint h1;
if (parameters [p_handle1].is_user<db::DPoint> ()) {
h1 = parameters [p_handle1].to_user<db::DPoint> ();
if (parameters [p_actual_handle1].is_user<db::DPoint> ()) {
h1 = parameters [p_actual_handle1].to_user<db::DPoint> ();
}
double a2u = parameters [p_actual_end_angle].to_double ();
double a2 = parameters [p_end_angle].to_double ();
double a2u = parameters [p_end_angle].to_double ();
double a2 = parameters [p_actual_end_angle].to_double ();
db::DPoint h2u;
if (parameters [p_actual_handle2].is_user<db::DPoint> ()) {
h2u = parameters [p_actual_handle2].to_user<db::DPoint> ();
if (parameters [p_handle2].is_user<db::DPoint> ()) {
h2u = parameters [p_handle2].to_user<db::DPoint> ();
}
db::DPoint h2;
if (parameters [p_handle2].is_user<db::DPoint> ()) {
h2 = parameters [p_handle2].to_user<db::DPoint> ();
if (parameters [p_actual_handle2].is_user<db::DPoint> ()) {
h2 = parameters [p_actual_handle2].to_user<db::DPoint> ();
}
if (fabs (ru1 - r1) > 1e-6 || fabs (ru2 - r2) > 1e-6 || fabs (a1u - a1) > 1e-6 || fabs (a2u - a2) > 1e-6) {
@ -118,8 +118,8 @@ BasicArc::coerce_parameters (const db::Layout & /*layout*/, db::pcell_parameters
h1u = db::DPoint (r1 * cos (a1 / 180.0 * M_PI), r1 * sin (a1 / 180.0 * M_PI));
h2u = db::DPoint (r2 * cos (a2 / 180.0 * M_PI), r2 * sin (a2 / 180.0 * M_PI));
parameters [p_handle1] = h1u;
parameters [p_handle2] = h2u;
parameters [p_actual_handle1] = h1u;
parameters [p_actual_handle2] = h2u;
} else if (h1u.distance (h1) > 1e-6 || h2u.distance (h2) > 1e-6) {
@ -135,20 +135,20 @@ BasicArc::coerce_parameters (const db::Layout & /*layout*/, db::pcell_parameters
h1u = h1;
h2u = h2;
parameters [p_radius1] = ru1;
parameters [p_radius2] = ru2;
parameters [p_start_angle] = a1u;
parameters [p_end_angle] = a2u;
parameters [p_actual_radius1] = ru1;
parameters [p_actual_radius2] = ru2;
parameters [p_actual_start_angle] = a1u;
parameters [p_actual_end_angle] = a2u;
}
// set the hidden used radius parameter
parameters [p_actual_radius1] = ru1;
parameters [p_actual_radius2] = ru2;
parameters [p_actual_start_angle] = a1u;
parameters [p_actual_end_angle] = a2u;
parameters [p_actual_handle1] = h1u;
parameters [p_actual_handle2] = h2u;
parameters [p_radius1] = ru1;
parameters [p_radius2] = ru2;
parameters [p_start_angle] = a1u;
parameters [p_end_angle] = a2u;
parameters [p_handle1] = h1u;
parameters [p_handle2] = h2u;
}
void
@ -158,10 +158,10 @@ BasicArc::produce (const db::Layout &layout, const std::vector<unsigned int> &la
return;
}
double r1 = parameters [p_actual_radius1].to_double () / layout.dbu ();
double r2 = parameters [p_actual_radius2].to_double () / layout.dbu ();
double a1 = parameters [p_actual_start_angle].to_double ();
double a2 = parameters [p_actual_end_angle].to_double ();
double r1 = parameters [p_radius1].to_double () / layout.dbu ();
double r2 = parameters [p_radius2].to_double () / layout.dbu ();
double a1 = parameters [p_start_angle].to_double ();
double a2 = parameters [p_end_angle].to_double ();
if (a2 < a1 - 1e-6) {
a2 += 360 * ceil ((a1 - a2) / 360.0 + 1e-6);
}
@ -205,8 +205,8 @@ std::string
BasicArc::get_display_name (const db::pcell_parameters_type &parameters) const
{
return "ARC(l=" + std::string (parameters [p_layer].to_string ()) +
",r=" + tl::to_string (parameters [p_actual_radius1].to_double ()) +
".." + tl::to_string (parameters [p_actual_radius2].to_double ()) +
",r=" + tl::to_string (parameters [p_radius1].to_double ()) +
".." + tl::to_string (parameters [p_radius2].to_double ()) +
",a=" + tl::to_string (parameters [p_start_angle].to_double (), 6) +
".." + tl::to_string (parameters [p_end_angle].to_double (), 6) +
",n=" + tl::to_string (parameters [p_npoints].to_int ()) +
@ -224,51 +224,49 @@ BasicArc::get_parameter_declarations () const
parameters.back ().set_type (db::PCellParameterDeclaration::t_layer);
parameters.back ().set_description (tl::to_string (tr ("Layer")));
// parameter #1: radius
// parameter #1: radius
// This is a shadow parameter to receive the used radius1
tl_assert (parameters.size () == p_radius1);
parameters.push_back (db::PCellParameterDeclaration ("radius1"));
parameters.back ().set_type (db::PCellParameterDeclaration::t_double);
parameters.back ().set_description (tl::to_string (tr ("Radius 1")));
parameters.back ().set_default (0.1);
parameters.back ().set_unit (tl::to_string (tr ("micron")));
parameters.back ().set_hidden (true);
// parameter #2: radius
// This is a shadow parameter to receive the used radius2
tl_assert (parameters.size () == p_radius2);
parameters.push_back (db::PCellParameterDeclaration ("radius2"));
parameters.back ().set_type (db::PCellParameterDeclaration::t_double);
parameters.back ().set_description (tl::to_string (tr ("Radius 2")));
parameters.back ().set_default (0.2);
parameters.back ().set_unit (tl::to_string (tr ("micron")));
parameters.back ().set_hidden (true);
// parameter #3: start angle
// This is a shadow parameter to receive the used start angle
tl_assert (parameters.size () == p_start_angle);
parameters.push_back (db::PCellParameterDeclaration ("a1"));
parameters.back ().set_type (db::PCellParameterDeclaration::t_double);
parameters.back ().set_description (tl::to_string (tr ("Start angle")));
parameters.back ().set_default (0);
parameters.back ().set_unit (tl::to_string (tr ("degree")));
parameters.back ().set_hidden (true);
// parameter #4: end angle
// This is a shadow parameter to receive the used end angle
tl_assert (parameters.size () == p_end_angle);
parameters.push_back (db::PCellParameterDeclaration ("a2"));
parameters.back ().set_type (db::PCellParameterDeclaration::t_double);
parameters.back ().set_description (tl::to_string (tr ("End angle")));
parameters.back ().set_default (90);
parameters.back ().set_unit (tl::to_string (tr ("degree")));
parameters.back ().set_hidden (true);
// parameter #5: handle 1
// This is a shadow parameter to keep the current handle position and to determine
// whether the handle changed
tl_assert (parameters.size () == p_handle1);
parameters.push_back (db::PCellParameterDeclaration ("handle1"));
parameters.back ().set_type (db::PCellParameterDeclaration::t_shape);
parameters.back ().set_default (db::DPoint (0.1, 0));
parameters.back ().set_description (tl::to_string (tr ("S")));
parameters.back ().set_hidden (true);
// parameter #6: handle 1
// This is a shadow parameter to keep the current handle position and to determine
// whether the handle changed
tl_assert (parameters.size () == p_handle2);
parameters.push_back (db::PCellParameterDeclaration ("handle2"));
parameters.back ().set_type (db::PCellParameterDeclaration::t_shape);
parameters.back ().set_default (db::DPoint (0, 0.1));
parameters.back ().set_description (tl::to_string (tr ("E")));
parameters.back ().set_hidden (true);
// parameter #7: number of points
tl_assert (parameters.size () == p_npoints);
@ -281,41 +279,47 @@ BasicArc::get_parameter_declarations () const
tl_assert (parameters.size () == p_actual_radius1);
parameters.push_back (db::PCellParameterDeclaration ("actual_radius1"));
parameters.back ().set_type (db::PCellParameterDeclaration::t_double);
parameters.back ().set_default (0.0);
parameters.back ().set_hidden (true);
parameters.back ().set_description (tl::to_string (tr ("Radius 1")));
parameters.back ().set_unit (tl::to_string (tr ("micron")));
parameters.back ().set_default (0.5);
// parameter #9: used radius 2
tl_assert (parameters.size () == p_actual_radius2);
parameters.push_back (db::PCellParameterDeclaration ("actual_radius2"));
parameters.back ().set_type (db::PCellParameterDeclaration::t_double);
parameters.back ().set_default (0.0);
parameters.back ().set_hidden (true);
parameters.back ().set_description (tl::to_string (tr ("Radius 2")));
parameters.back ().set_unit (tl::to_string (tr ("micron")));
parameters.back ().set_default (1.0);
// parameter #10: used start angle
tl_assert (parameters.size () == p_actual_start_angle);
parameters.push_back (db::PCellParameterDeclaration ("actual_start_angle"));
parameters.back ().set_type (db::PCellParameterDeclaration::t_double);
parameters.back ().set_description (tl::to_string (tr ("Start angle")));
parameters.back ().set_unit (tl::to_string (tr ("degree")));
parameters.back ().set_default (0.0);
parameters.back ().set_hidden (true);
// parameter #11: used end angle
tl_assert (parameters.size () == p_actual_end_angle);
parameters.push_back (db::PCellParameterDeclaration ("actual_end_angle"));
parameters.back ().set_type (db::PCellParameterDeclaration::t_double);
parameters.back ().set_default (0.0);
parameters.back ().set_hidden (true);
parameters.back ().set_description (tl::to_string (tr ("End angle")));
parameters.back ().set_unit (tl::to_string (tr ("degree")));
parameters.back ().set_default (90.0);
// parameter #12: used handle 1
tl_assert (parameters.size () == p_actual_handle1);
parameters.push_back (db::PCellParameterDeclaration ("actual_handle1"));
parameters.back ().set_type (db::PCellParameterDeclaration::t_shape);
parameters.back ().set_hidden (true);
parameters.back ().set_description (tl::to_string (tr ("S")));
parameters.back ().set_default (db::DPoint (0.5, 0.0));
// parameter #13: used handle 2
tl_assert (parameters.size () == p_actual_handle2);
parameters.push_back (db::PCellParameterDeclaration ("actual_handle2"));
parameters.back ().set_type (db::PCellParameterDeclaration::t_shape);
parameters.back ().set_hidden (true);
parameters.back ().set_description (tl::to_string (tr ("E")));
parameters.back ().set_default (db::DPoint (0.0, 1.0));
tl_assert (parameters.size () == p_total);
return parameters;

View File

@ -64,7 +64,7 @@ BasicCircle::parameters_from_shape (const db::Layout &layout, const db::Shape &s
// use map_parameters to create defaults for the other parameters
std::map<size_t, tl::Variant> nm;
nm.insert (std::make_pair (p_layer, tl::Variant (layout.get_properties (layer))));
nm.insert (std::make_pair (p_radius, tl::Variant (0.5 * std::min (dbox.width (), dbox.height ()))));
nm.insert (std::make_pair (p_actual_radius, tl::Variant (0.5 * std::min (dbox.width (), dbox.height ()))));
return map_parameters (nm);
}
@ -88,8 +88,8 @@ BasicCircle::coerce_parameters (const db::Layout & /*layout*/, db::pcell_paramet
return;
}
double ru = parameters [p_actual_radius].to_double ();
double r = parameters [p_radius].to_double ();
double ru = parameters [p_radius].to_double ();
double r = parameters [p_actual_radius].to_double ();
double rs = ru;
if (parameters [p_handle].is_user <db::DPoint> ()) {
@ -104,11 +104,11 @@ BasicCircle::coerce_parameters (const db::Layout & /*layout*/, db::pcell_paramet
// the handle has changed: use this
ru = rs;
r = rs;
parameters [p_radius] = r;
parameters [p_actual_radius] = r;
}
// set the hidden used radius parameter
parameters [p_actual_radius] = ru;
parameters [p_radius] = ru;
}
void
@ -118,7 +118,7 @@ BasicCircle::produce (const db::Layout &layout, const std::vector<unsigned int>
return;
}
double r = parameters [p_actual_radius].to_double () / layout.dbu ();
double r = parameters [p_radius].to_double () / layout.dbu ();
int n = std::max (3, parameters [p_npoints].to_int ());
std::vector <db::Point> points;
@ -143,7 +143,7 @@ std::string
BasicCircle::get_display_name (const db::pcell_parameters_type &parameters) const
{
return "CIRCLE(l=" + std::string (parameters [p_layer].to_string ()) +
",r=" + tl::to_string (parameters [p_actual_radius].to_double ()) +
",r=" + tl::to_string (parameters [p_radius].to_double ()) +
",n=" + tl::to_string (parameters [p_npoints].to_int ()) +
")";
}
@ -159,19 +159,19 @@ BasicCircle::get_parameter_declarations () const
parameters.back ().set_type (db::PCellParameterDeclaration::t_layer);
parameters.back ().set_description (tl::to_string (tr ("Layer")));
// parameter #1: radius
// parameter #1: radius (shadow, hidden)
// This parameter is updated by "coerce_parameters" from "actual_radius" or "handle",
// whichever changed.
tl_assert (parameters.size () == p_radius);
parameters.push_back (db::PCellParameterDeclaration ("radius"));
parameters.back ().set_type (db::PCellParameterDeclaration::t_double);
parameters.back ().set_description (tl::to_string (tr ("Radius")));
parameters.back ().set_default (0.1);
parameters.back ().set_unit (tl::to_string (tr ("micron")));
parameters.back ().set_hidden (true);
// parameter #2: handle
tl_assert (parameters.size () == p_handle);
parameters.push_back (db::PCellParameterDeclaration ("handle"));
parameters.back ().set_type (db::PCellParameterDeclaration::t_shape);
parameters.back ().set_default (db::DPoint (-0.1, 0));
parameters.back ().set_default (db::DPoint (-1.0, 0));
parameters.back ().set_description (tl::to_string (tr ("R")));
// parameter #3: number of points
@ -181,12 +181,13 @@ BasicCircle::get_parameter_declarations () const
parameters.back ().set_description (tl::to_string (tr ("Number of points")));
parameters.back ().set_default (64);
// parameter #4: used radius
// parameter #4: radius (entry field)
tl_assert (parameters.size () == p_actual_radius);
parameters.push_back (db::PCellParameterDeclaration ("actual_radius"));
parameters.back ().set_description (tl::to_string (tr ("Radius")));
parameters.back ().set_unit (tl::to_string (tr ("micron")));
parameters.back ().set_type (db::PCellParameterDeclaration::t_double);
parameters.back ().set_default (0.0);
parameters.back ().set_hidden (true);
parameters.back ().set_default (1.0);
return parameters;
}

View File

@ -67,8 +67,8 @@ BasicDonut::parameters_from_shape (const db::Layout &layout, const db::Shape &sh
// use map_parameters to create defaults for the other parameters
std::map<size_t, tl::Variant> nm;
nm.insert (std::make_pair (p_layer, tl::Variant (layout.get_properties (layer))));
nm.insert (std::make_pair (p_radius1, tl::Variant (0.5 * std::min (dbox.width (), dbox.height ()))));
nm.insert (std::make_pair (p_radius2, tl::Variant (0.25 * std::min (dbox.width (), dbox.height ()))));
nm.insert (std::make_pair (p_actual_radius1, tl::Variant (0.5 * std::min (dbox.width (), dbox.height ()))));
nm.insert (std::make_pair (p_actual_radius2, tl::Variant (0.25 * std::min (dbox.width (), dbox.height ()))));
return map_parameters (nm);
}
@ -92,15 +92,15 @@ BasicDonut::coerce_parameters (const db::Layout & /*layout*/, db::pcell_paramete
return;
}
double ru1 = parameters [p_actual_radius1].to_double ();
double r1 = parameters [p_radius1].to_double ();
double ru1 = parameters [p_radius1].to_double ();
double r1 = parameters [p_actual_radius1].to_double ();
double rs1 = ru1;
if (parameters [p_handle1].is_user <db::DPoint> ()) {
rs1 = parameters [p_handle1].to_user <db::DPoint> ().distance ();
}
double ru2 = parameters [p_actual_radius2].to_double ();
double r2 = parameters [p_radius2].to_double ();
double ru2 = parameters [p_radius2].to_double ();
double r2 = parameters [p_actual_radius2].to_double ();
double rs2 = ru2;
if (parameters [p_handle2].is_user <db::DPoint> ()) {
rs2 = parameters [p_handle2].to_user <db::DPoint> ().distance ();
@ -118,13 +118,13 @@ BasicDonut::coerce_parameters (const db::Layout & /*layout*/, db::pcell_paramete
r1 = rs1;
ru2 = rs2;
r2 = rs2;
parameters [p_radius1] = r1;
parameters [p_radius2] = r2;
parameters [p_actual_radius1] = r1;
parameters [p_actual_radius2] = r2;
}
// set the hidden used radius parameter
parameters [p_actual_radius1] = ru1;
parameters [p_actual_radius2] = ru2;
parameters [p_radius1] = ru1;
parameters [p_radius2] = ru2;
}
void
@ -134,8 +134,8 @@ BasicDonut::produce (const db::Layout &layout, const std::vector<unsigned int> &
return;
}
double r1 = parameters [p_actual_radius1].to_double () / layout.dbu ();
double r2 = parameters [p_actual_radius2].to_double () / layout.dbu ();
double r1 = parameters [p_radius1].to_double () / layout.dbu ();
double r2 = parameters [p_radius2].to_double () / layout.dbu ();
int n = std::max (3, parameters [p_npoints].to_int ());
std::vector <db::Point> points;
@ -170,8 +170,8 @@ std::string
BasicDonut::get_display_name (const db::pcell_parameters_type &parameters) const
{
return "DONUT(l=" + std::string (parameters [p_layer].to_string ()) +
",r=" + tl::to_string (parameters [p_actual_radius1].to_double ()) +
".." + tl::to_string (parameters [p_actual_radius2].to_double ()) +
",r=" + tl::to_string (parameters [p_radius1].to_double ()) +
".." + tl::to_string (parameters [p_radius2].to_double ()) +
",n=" + tl::to_string (parameters [p_npoints].to_int ()) +
")";
}
@ -188,33 +188,29 @@ BasicDonut::get_parameter_declarations () const
parameters.back ().set_description (tl::to_string (tr ("Layer")));
// parameter #1: radius1
// This is a shadow parameter to receive the used first radius
tl_assert (parameters.size () == p_radius1);
parameters.push_back (db::PCellParameterDeclaration ("radius1"));
parameters.back ().set_type (db::PCellParameterDeclaration::t_double);
parameters.back ().set_description (tl::to_string (tr ("Radius 1")));
parameters.back ().set_default (0.1);
parameters.back ().set_unit (tl::to_string (tr ("micron")));
parameters.back ().set_hidden (true);
// parameter #2: radius2
// This is a shadow parameter to receive the used second radius
tl_assert (parameters.size () == p_radius2);
parameters.push_back (db::PCellParameterDeclaration ("radius2"));
parameters.back ().set_type (db::PCellParameterDeclaration::t_double);
parameters.back ().set_description (tl::to_string (tr ("Radius 2")));
parameters.back ().set_default (0.2);
parameters.back ().set_unit (tl::to_string (tr ("micron")));
parameters.back ().set_hidden (true);
// parameter #3: handle 1
tl_assert (parameters.size () == p_handle1);
parameters.push_back (db::PCellParameterDeclaration ("handle1"));
parameters.back ().set_type (db::PCellParameterDeclaration::t_shape);
parameters.back ().set_default (db::DPoint (-0.1, 0));
parameters.back ().set_description (tl::to_string (tr ("R1")));
// parameter #4: handle 2
tl_assert (parameters.size () == p_handle2);
parameters.push_back (db::PCellParameterDeclaration ("handle2"));
parameters.back ().set_type (db::PCellParameterDeclaration::t_shape);
parameters.back ().set_default (db::DPoint (-0.2, 0));
parameters.back ().set_description (tl::to_string (tr ("R2")));
// parameter #5: number of points
@ -228,15 +224,17 @@ BasicDonut::get_parameter_declarations () const
tl_assert (parameters.size () == p_actual_radius1);
parameters.push_back (db::PCellParameterDeclaration ("actual_radius1"));
parameters.back ().set_type (db::PCellParameterDeclaration::t_double);
parameters.back ().set_default (0.0);
parameters.back ().set_hidden (true);
parameters.back ().set_description (tl::to_string (tr ("Radius 1")));
parameters.back ().set_unit (tl::to_string (tr ("micron")));
parameters.back ().set_default (0.5);
// parameter #7: used radius 2
tl_assert (parameters.size () == p_actual_radius2);
parameters.push_back (db::PCellParameterDeclaration ("actual_radius2"));
parameters.back ().set_type (db::PCellParameterDeclaration::t_double);
parameters.back ().set_default (0.0);
parameters.back ().set_hidden (true);
parameters.back ().set_description (tl::to_string (tr ("Radius 2")));
parameters.back ().set_unit (tl::to_string (tr ("micron")));
parameters.back ().set_default (1.0);
return parameters;
}

View File

@ -67,8 +67,8 @@ BasicEllipse::parameters_from_shape (const db::Layout &layout, const db::Shape &
// use map_parameters to create defaults for the other parameters
std::map<size_t, tl::Variant> nm;
nm.insert (std::make_pair (p_layer, tl::Variant (layout.get_properties (layer))));
nm.insert (std::make_pair (p_radius_x, tl::Variant (0.5 * dbox.width ())));
nm.insert (std::make_pair (p_radius_y, tl::Variant (0.5 * dbox.height ())));
nm.insert (std::make_pair (p_actual_radius_x, tl::Variant (0.5 * dbox.width ())));
nm.insert (std::make_pair (p_actual_radius_y, tl::Variant (0.5 * dbox.height ())));
return map_parameters (nm);
}
@ -92,8 +92,8 @@ BasicEllipse::coerce_parameters (const db::Layout & /*layout*/, db::pcell_parame
return;
}
double ru_x = parameters [p_actual_radius_x].to_double ();
double r_x = parameters [p_radius_x].to_double ();
double ru_x = parameters [p_radius_x].to_double ();
double r_x = parameters [p_actual_radius_x].to_double ();
double rs_x = ru_x;
if (parameters [p_handle_x].is_user <db::DPoint> ()) {
@ -108,16 +108,16 @@ BasicEllipse::coerce_parameters (const db::Layout & /*layout*/, db::pcell_parame
// the handle has changed: use this
ru_x = rs_x;
r_x = rs_x;
parameters [p_radius_x] = r_x;
parameters [p_actual_radius_x] = r_x;
parameters [p_handle_x] = db::DPoint (-r_x, 0);
}
// set the hidden used radius parameter
parameters [p_actual_radius_x] = ru_x;
parameters [p_radius_x] = ru_x;
// do the same for the y radius
double ru_y = parameters [p_actual_radius_y].to_double ();
double r_y = parameters [p_radius_y].to_double ();
double ru_y = parameters [p_radius_y].to_double ();
double r_y = parameters [p_actual_radius_y].to_double ();
double rs_y = ru_y;
if (parameters [p_handle_y].is_user <db::DPoint> ()) {
@ -132,12 +132,12 @@ BasicEllipse::coerce_parameters (const db::Layout & /*layout*/, db::pcell_parame
// the handle has changed: use this
ru_y = rs_y;
r_y = rs_y;
parameters [p_radius_y] = r_y;
parameters [p_actual_radius_y] = r_y;
parameters [p_handle_y] = db::DPoint (0, r_y);
}
// set the hidden used radius parameter
parameters [p_actual_radius_y] = ru_y;
parameters [p_radius_y] = ru_y;
}
void
@ -147,8 +147,8 @@ BasicEllipse::produce (const db::Layout &layout, const std::vector<unsigned int>
return;
}
double r_x = parameters [p_actual_radius_x].to_double () / layout.dbu ();
double r_y = parameters [p_actual_radius_y].to_double () / layout.dbu ();
double r_x = parameters [p_radius_x].to_double () / layout.dbu ();
double r_y = parameters [p_radius_y].to_double () / layout.dbu ();
int n = std::max (3, parameters [p_npoints].to_int ());
std::vector <db::Point> points;
@ -174,8 +174,8 @@ std::string
BasicEllipse::get_display_name (const db::pcell_parameters_type &parameters) const
{
return "ELLIPSE(l=" + std::string (parameters [p_layer].to_string ()) +
",rx=" + tl::to_string (parameters [p_actual_radius_x].to_double ()) +
",ry=" + tl::to_string (parameters [p_actual_radius_y].to_double ()) +
",rx=" + tl::to_string (parameters [p_radius_x].to_double ()) +
",ry=" + tl::to_string (parameters [p_radius_y].to_double ()) +
",n=" + tl::to_string (parameters [p_npoints].to_int ()) +
")";
}
@ -195,30 +195,28 @@ BasicEllipse::get_parameter_declarations () const
tl_assert (parameters.size () == p_radius_x);
parameters.push_back (db::PCellParameterDeclaration ("radius_x"));
parameters.back ().set_type (db::PCellParameterDeclaration::t_double);
parameters.back ().set_description (tl::to_string (tr ("Radius (x)")));
parameters.back ().set_default (0.1);
parameters.back ().set_unit (tl::to_string (tr ("micron")));
parameters.back ().set_hidden (true);
// parameter #2: y radius
// This is a shadow parameter to receive the used y radius
tl_assert (parameters.size () == p_radius_y);
parameters.push_back (db::PCellParameterDeclaration ("radius_y"));
parameters.back ().set_type (db::PCellParameterDeclaration::t_double);
parameters.back ().set_description (tl::to_string (tr ("Radius (y)")));
parameters.back ().set_default (0.1);
parameters.back ().set_unit (tl::to_string (tr ("micron")));
parameters.back ().set_hidden (true);
// parameter #3: x handle
// This is a shadow parameter to receive the used x radius
tl_assert (parameters.size () == p_handle_x);
parameters.push_back (db::PCellParameterDeclaration ("handle_x"));
parameters.back ().set_type (db::PCellParameterDeclaration::t_shape);
parameters.back ().set_default (db::DPoint (-0.2, 0));
parameters.back ().set_default (db::DPoint (-1.0, 0));
parameters.back ().set_description (tl::to_string (tr ("Rx")));
// parameter #4: x handle
tl_assert (parameters.size () == p_handle_y);
parameters.push_back (db::PCellParameterDeclaration ("handle_y"));
parameters.back ().set_type (db::PCellParameterDeclaration::t_shape);
parameters.back ().set_default (db::DPoint (-0.1, 0));
parameters.back ().set_default (db::DPoint (0, 0.5));
parameters.back ().set_description (tl::to_string (tr ("Ry")));
// parameter #5: number of points
@ -232,15 +230,17 @@ BasicEllipse::get_parameter_declarations () const
tl_assert (parameters.size () == p_actual_radius_x);
parameters.push_back (db::PCellParameterDeclaration ("actual_radius_x"));
parameters.back ().set_type (db::PCellParameterDeclaration::t_double);
parameters.back ().set_default (0.0);
parameters.back ().set_hidden (true);
parameters.back ().set_description (tl::to_string (tr ("Radius (x)")));
parameters.back ().set_unit (tl::to_string (tr ("micron")));
parameters.back ().set_default (1.0);
// parameter #6: used y radius
tl_assert (parameters.size () == p_actual_radius_y);
parameters.push_back (db::PCellParameterDeclaration ("actual_radius_y"));
parameters.back ().set_type (db::PCellParameterDeclaration::t_double);
parameters.back ().set_default (0.0);
parameters.back ().set_hidden (true);
parameters.back ().set_description (tl::to_string (tr ("Radius (y)")));
parameters.back ().set_unit (tl::to_string (tr ("micron")));
parameters.back ().set_default (0.5);
return parameters;
}

View File

@ -70,38 +70,38 @@ BasicPie::coerce_parameters (const db::Layout & /*layout*/, db::pcell_parameters
return;
}
double ru = parameters [p_actual_radius].to_double ();
double r = parameters [p_radius].to_double ();
double ru = parameters [p_radius].to_double ();
double r = parameters [p_actual_radius].to_double ();
double rs = ru;
if (parameters [p_handle1].is_user <db::DPoint> ()) {
rs = parameters [p_handle1].to_user <db::DPoint> ().distance ();
if (parameters [p_handle2].is_user <db::DPoint> ()) {
rs = std::max (rs, parameters [p_handle2].to_user <db::DPoint> ().distance ());
if (parameters [p_actual_handle1].is_user <db::DPoint> ()) {
rs = parameters [p_actual_handle1].to_user <db::DPoint> ().distance ();
if (parameters [p_actual_handle2].is_user <db::DPoint> ()) {
rs = std::max (rs, parameters [p_actual_handle2].to_user <db::DPoint> ().distance ());
}
} else if (parameters [p_handle2].is_user <db::DPoint> ()) {
rs = parameters [p_handle2].to_user <db::DPoint> ().distance ();
} else if (parameters [p_actual_handle2].is_user <db::DPoint> ()) {
rs = parameters [p_actual_handle2].to_user <db::DPoint> ().distance ();
}
double a1u = parameters [p_actual_start_angle].to_double ();
double a1 = parameters [p_start_angle].to_double ();
double a1u = parameters [p_start_angle].to_double ();
double a1 = parameters [p_actual_start_angle].to_double ();
db::DPoint h1u;
if (parameters [p_actual_handle1].is_user<db::DPoint> ()) {
h1u = parameters [p_actual_handle1].to_user<db::DPoint> ();
if (parameters [p_handle1].is_user<db::DPoint> ()) {
h1u = parameters [p_handle1].to_user<db::DPoint> ();
}
db::DPoint h1;
if (parameters [p_handle1].is_user<db::DPoint> ()) {
h1 = parameters [p_handle1].to_user<db::DPoint> ();
if (parameters [p_actual_handle1].is_user<db::DPoint> ()) {
h1 = parameters [p_actual_handle1].to_user<db::DPoint> ();
}
double a2u = parameters [p_actual_end_angle].to_double ();
double a2 = parameters [p_end_angle].to_double ();
double a2u = parameters [p_end_angle].to_double ();
double a2 = parameters [p_actual_end_angle].to_double ();
db::DPoint h2u;
if (parameters [p_actual_handle2].is_user<db::DPoint> ()) {
h2u = parameters [p_actual_handle2].to_user<db::DPoint> ();
if (parameters [p_handle2].is_user<db::DPoint> ()) {
h2u = parameters [p_handle2].to_user<db::DPoint> ();
}
db::DPoint h2;
if (parameters [p_handle2].is_user<db::DPoint> ()) {
h2 = parameters [p_handle2].to_user<db::DPoint> ();
if (parameters [p_actual_handle2].is_user<db::DPoint> ()) {
h2 = parameters [p_actual_handle2].to_user<db::DPoint> ();
}
if (fabs (ru - r) > 1e-6 || fabs (a1u - a1) > 1e-6 || fabs (a2u - a2) > 1e-6) {
@ -113,8 +113,8 @@ BasicPie::coerce_parameters (const db::Layout & /*layout*/, db::pcell_parameters
h1u = db::DPoint (r * cos (a1 / 180.0 * M_PI), r * sin (a1 / 180.0 * M_PI));
h2u = db::DPoint (r * cos (a2 / 180.0 * M_PI), r * sin (a2 / 180.0 * M_PI));
parameters [p_handle1] = h1u;
parameters [p_handle2] = h2u;
parameters [p_actual_handle1] = h1u;
parameters [p_actual_handle2] = h2u;
} else if (h1u.distance (h1) > 1e-6 || h2u.distance (h2) > 1e-6) {
@ -129,18 +129,18 @@ BasicPie::coerce_parameters (const db::Layout & /*layout*/, db::pcell_parameters
h1u = h1;
h2u = h2;
parameters [p_radius] = ru;
parameters [p_start_angle] = a1u;
parameters [p_end_angle] = a2u;
parameters [p_actual_radius] = ru;
parameters [p_actual_start_angle] = a1u;
parameters [p_actual_end_angle] = a2u;
}
// set the hidden used radius parameter
parameters [p_actual_radius] = ru;
parameters [p_actual_start_angle] = a1u;
parameters [p_actual_end_angle] = a2u;
parameters [p_actual_handle1] = h1u;
parameters [p_actual_handle2] = h2u;
parameters [p_radius] = ru;
parameters [p_start_angle] = a1u;
parameters [p_end_angle] = a2u;
parameters [p_handle1] = h1u;
parameters [p_handle2] = h2u;
}
void
@ -150,9 +150,9 @@ BasicPie::produce (const db::Layout &layout, const std::vector<unsigned int> &la
return;
}
double r = parameters [p_actual_radius].to_double () / layout.dbu ();
double a1 = parameters [p_actual_start_angle].to_double ();
double a2 = parameters [p_actual_end_angle].to_double ();
double r = parameters [p_radius].to_double () / layout.dbu ();
double a1 = parameters [p_start_angle].to_double ();
double a2 = parameters [p_end_angle].to_double ();
if (a2 < a1 - 1e-6) {
a2 += 360 * ceil ((a1 - a2) / 360.0 + 1e-6);
}
@ -187,7 +187,7 @@ std::string
BasicPie::get_display_name (const db::pcell_parameters_type &parameters) const
{
return "PIE(l=" + std::string (parameters [p_layer].to_string ()) +
",r=" + tl::to_string (parameters [p_actual_radius].to_double ()) +
",r=" + tl::to_string (parameters [p_radius].to_double ()) +
",a=" + tl::to_string (parameters [p_start_angle].to_double (), 6) +
".." + tl::to_string (parameters [p_end_angle].to_double (), 6) +
",n=" + tl::to_string (parameters [p_npoints].to_int ()) +
@ -206,42 +206,42 @@ BasicPie::get_parameter_declarations () const
parameters.back ().set_description (tl::to_string (tr ("Layer")));
// parameter #1: radius
// This parameter is updated by "coerce_parameters" from "actual_radius" or the handles,
// whichever changed.
tl_assert (parameters.size () == p_radius);
parameters.push_back (db::PCellParameterDeclaration ("radius"));
parameters.back ().set_type (db::PCellParameterDeclaration::t_double);
parameters.back ().set_description (tl::to_string (tr ("Radius")));
parameters.back ().set_default (0.1);
parameters.back ().set_unit (tl::to_string (tr ("micron")));
parameters.back ().set_hidden (true);
// parameter #2: start angle
// This is a shadow parameter to keep the final start angle
tl_assert (parameters.size () == p_start_angle);
parameters.push_back (db::PCellParameterDeclaration ("a1"));
parameters.back ().set_type (db::PCellParameterDeclaration::t_double);
parameters.back ().set_description (tl::to_string (tr ("Start angle")));
parameters.back ().set_default (0);
parameters.back ().set_unit (tl::to_string (tr ("degree")));
parameters.back ().set_hidden (true);
// parameter #3: end angle
// This is a shadow parameter to keep the final end angle
tl_assert (parameters.size () == p_end_angle);
parameters.push_back (db::PCellParameterDeclaration ("a2"));
parameters.back ().set_type (db::PCellParameterDeclaration::t_double);
parameters.back ().set_description (tl::to_string (tr ("End angle")));
parameters.back ().set_default (90);
parameters.back ().set_unit (tl::to_string (tr ("degree")));
parameters.back ().set_hidden (true);
// parameter #4: handle 1
tl_assert (parameters.size () == p_handle1);
// This is a shadow parameter to keep the current handle position and to determine
// whether the handle changed
parameters.push_back (db::PCellParameterDeclaration ("handle1"));
parameters.back ().set_type (db::PCellParameterDeclaration::t_shape);
parameters.back ().set_default (db::DPoint (0.1, 0));
parameters.back ().set_description (tl::to_string (tr ("S")));
parameters.back ().set_hidden (true);
// parameter #5: handle 1
// This is a shadow parameter to keep the current handle position and to determine
// whether the handle changed
tl_assert (parameters.size () == p_handle2);
parameters.push_back (db::PCellParameterDeclaration ("handle2"));
parameters.back ().set_type (db::PCellParameterDeclaration::t_shape);
parameters.back ().set_default (db::DPoint (0, 0.1));
parameters.back ().set_description (tl::to_string (tr ("E")));
parameters.back ().set_hidden (true);
// parameter #6: number of points
tl_assert (parameters.size () == p_npoints);
@ -254,34 +254,39 @@ BasicPie::get_parameter_declarations () const
tl_assert (parameters.size () == p_actual_radius);
parameters.push_back (db::PCellParameterDeclaration ("actual_radius"));
parameters.back ().set_type (db::PCellParameterDeclaration::t_double);
parameters.back ().set_default (0.0);
parameters.back ().set_hidden (true);
parameters.back ().set_description (tl::to_string (tr ("Radius")));
parameters.back ().set_unit (tl::to_string (tr ("micron")));
parameters.back ().set_default (1.0);
// parameter #8: used start angle
tl_assert (parameters.size () == p_actual_start_angle);
parameters.push_back (db::PCellParameterDeclaration ("actual_start_angle"));
parameters.back ().set_type (db::PCellParameterDeclaration::t_double);
parameters.back ().set_description (tl::to_string (tr ("Start angle")));
parameters.back ().set_unit (tl::to_string (tr ("degree")));
parameters.back ().set_default (0.0);
parameters.back ().set_hidden (true);
// parameter #9: used end angle
tl_assert (parameters.size () == p_actual_end_angle);
parameters.push_back (db::PCellParameterDeclaration ("actual_end_angle"));
parameters.back ().set_type (db::PCellParameterDeclaration::t_double);
parameters.back ().set_default (0.0);
parameters.back ().set_hidden (true);
parameters.back ().set_description (tl::to_string (tr ("End angle")));
parameters.back ().set_unit (tl::to_string (tr ("degree")));
parameters.back ().set_default (90.0);
// parameter #10: used handle 1
tl_assert (parameters.size () == p_actual_handle1);
parameters.push_back (db::PCellParameterDeclaration ("actual_handle1"));
parameters.back ().set_type (db::PCellParameterDeclaration::t_shape);
parameters.back ().set_hidden (true);
parameters.back ().set_description (tl::to_string (tr ("S")));
parameters.back ().set_default (db::DPoint (-1.0, 0.0));
// parameter #11: used handle 2
tl_assert (parameters.size () == p_actual_handle2);
parameters.push_back (db::PCellParameterDeclaration ("actual_handle2"));
parameters.back ().set_type (db::PCellParameterDeclaration::t_shape);
parameters.back ().set_hidden (true);
parameters.back ().set_description (tl::to_string (tr ("E")));
parameters.back ().set_default (db::DPoint (0.0, 1.0));
tl_assert (parameters.size () == p_total);
return parameters;

View File

@ -23,11 +23,764 @@
#include "tlUnitTest.h"
TEST(1)
{
EXPECT_EQ (1, 1); // avoids a compiler warning because of unreferenced _this
#include "dbLibrary.h"
#include "dbLibraryManager.h"
#include "dbReader.h"
#include "dbTestSupport.h"
// TODO: add tests for lib specific things
throw tl::CancelException (); // skip this test to indicate that there is nothing yet
#include "libBasicCircle.h"
TEST(1_Circle)
{
const size_t p_layer = 0;
const size_t p_radius = 1;
const size_t p_handle = 2;
const size_t p_npoints = 3;
const size_t p_actual_radius = 4;
const size_t p_total = 5;
db::Library *lib_basic = db::LibraryManager::instance ().lib_ptr_by_name ("Basic");
tl_assert (lib_basic);
db::Layout ly;
std::pair<bool, db::pcell_id_type> pc = lib_basic->layout ().pcell_by_name ("CIRCLE");
tl_assert (pc.first);
std::map<std::string, tl::Variant> params;
params["layer"] = db::LayerProperties (1, 0);
params["actual_radius"] = 10.0;
db::cell_index_type lib_cell;
db::Cell *circle;
std::vector<tl::Variant> plist;
lib_cell = lib_basic->layout ().get_pcell_variant_dict (pc.second, params);
circle = &ly.cell (ly.get_lib_proxy (lib_basic, lib_cell));
// change radius explicitly
// has radius 10um
EXPECT_EQ (circle->bbox ().to_string (), "(-10000,-10000;10000,10000)");
EXPECT_EQ (circle->get_display_name (), "Basic.CIRCLE(l=1/0,r=10,n=64)");
// only after Library::refresh the parameters get updated
EXPECT_EQ (ly.get_pcell_parameters (circle->cell_index ()) [p_radius].to_double (), 0.0);
lib_basic->refresh ();
EXPECT_EQ (circle->bbox ().to_string (), "(-10000,-10000;10000,10000)");
EXPECT_EQ (circle->get_display_name (), "Basic.CIRCLE(l=1/0,r=10,n=64)");
EXPECT_EQ (ly.get_pcell_parameters (circle->cell_index ()) [p_radius].to_double (), 10.0);
EXPECT_EQ (ly.get_pcell_parameters (circle->cell_index ()) [p_actual_radius].to_double (), 10.0);
// change radius explicitly
plist = ly.get_pcell_parameters (circle->cell_index ());
plist[p_actual_radius] = 9.0;
circle = &ly.cell (ly.get_pcell_variant_cell (circle->cell_index (), plist));
// as the radius is an input parameter, only after Library::refresh the other parameters get updated
EXPECT_EQ (ly.get_pcell_parameters (circle->cell_index ()) [p_radius].to_double (), 10.0);
lib_basic->refresh ();
EXPECT_EQ (circle->bbox ().to_string (), "(-9000,-9000;9000,9000)");
EXPECT_EQ (circle->get_display_name (), "Basic.CIRCLE(l=1/0,r=9,n=64)");
EXPECT_EQ (ly.get_pcell_parameters (circle->cell_index ()) [p_radius].to_double (), 9.0);
EXPECT_EQ (ly.get_pcell_parameters (circle->cell_index ()) [p_actual_radius].to_double (), 9.0);
// change handle explicitly
plist = ly.get_pcell_parameters (circle->cell_index ());
plist[p_handle] = db::DPoint (0.0, 8.0);
circle = &ly.cell (ly.get_pcell_variant_cell (circle->cell_index (), plist));
// as the handle is an input parameter, only after Library::refresh the other parameters get updated
EXPECT_EQ (ly.get_pcell_parameters (circle->cell_index ()) [p_actual_radius].to_double (), 9.0);
lib_basic->refresh ();
EXPECT_EQ (circle->bbox ().to_string (), "(-8000,-8000;8000,8000)");
EXPECT_EQ (circle->get_display_name (), "Basic.CIRCLE(l=1/0,r=8,n=64)");
EXPECT_EQ (ly.get_pcell_parameters (circle->cell_index ()) [p_radius].to_double (), 8.0);
EXPECT_EQ (ly.get_pcell_parameters (circle->cell_index ()) [p_actual_radius].to_double (), 8.0);
unsigned int l1 = ly.get_layer (db::LayerProperties (1, 0));
db::Shapes shapes;
db::Shape s = shapes.insert (db::Box (1000, 2000, 4000, 5000));
EXPECT_EQ (lib_basic->layout ().pcell_declaration (pc.second)->can_create_from_shape (ly, s, l1), true);
EXPECT_EQ (lib_basic->layout ().pcell_declaration (pc.second)->transformation_from_shape (ly, s, l1).to_string (), "r0 2500,3500");
plist = lib_basic->layout ().pcell_declaration (pc.second)->parameters_from_shape (ly, s, l1);
EXPECT_EQ (plist [p_layer].to_string (), "1/0");
EXPECT_EQ (plist [p_actual_radius].to_string (), "1.5");
}
TEST(2_Pie)
{
static size_t p_layer = 0;
static size_t p_radius = 1;
static size_t p_start_angle = 2;
static size_t p_end_angle = 3;
static size_t p_handle1 = 4;
static size_t p_handle2 = 5;
static size_t p_npoints = 6;
static size_t p_actual_radius = 7;
static size_t p_actual_start_angle = 8;
static size_t p_actual_end_angle = 9;
static size_t p_actual_handle1 = 10;
static size_t p_actual_handle2 = 11;
static size_t p_total = 12;
db::Library *lib_basic = db::LibraryManager::instance ().lib_ptr_by_name ("Basic");
tl_assert (lib_basic);
db::Layout ly;
std::pair<bool, db::pcell_id_type> pc = lib_basic->layout ().pcell_by_name ("PIE");
tl_assert (pc.first);
std::map<std::string, tl::Variant> params;
params["layer"] = db::LayerProperties (1, 0);
params["actual_radius"] = 10.0;
params["actual_start_angle"] = -90.0;
params["actual_end_angle"] = 0.0;
db::cell_index_type lib_cell;
db::Cell *pie;
std::vector<tl::Variant> plist;
lib_cell = lib_basic->layout ().get_pcell_variant_dict (pc.second, params);
pie = &ly.cell (ly.get_lib_proxy (lib_basic, lib_cell));
// change radius explicitly
// has radius 10um, but bbox isn't correct for now (because handle was not updated)
EXPECT_EQ (pie->bbox ().to_string (), "(-1000,-10000;10000,1000)");
EXPECT_EQ (pie->get_display_name (), "Basic.PIE(l=1/0,r=10,a=-90..0,n=64)");
// only after Library::refresh the parameters get updated and bbox is correct
EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_radius].to_double (), 0.0);
lib_basic->refresh ();
EXPECT_EQ (pie->bbox ().to_string (), "(0,-10000;10000,0)");
EXPECT_EQ (pie->get_display_name (), "Basic.PIE(l=1/0,r=10,a=-90..0,n=64)");
EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_radius].to_double (), 10.0);
EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_actual_radius].to_double (), 10.0);
EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_start_angle].to_double (), -90);
EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_actual_start_angle].to_double (), -90);
EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_end_angle].to_double (), 0);
EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_actual_end_angle].to_double (), 0);
// change radius explicitly
plist = ly.get_pcell_parameters (pie->cell_index ());
plist[p_actual_radius] = 9.0;
pie = &ly.cell (ly.get_pcell_variant_cell (pie->cell_index (), plist));
// as the radius is an input parameter, only after Library::refresh the other parameters get updated
EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_radius].to_double (), 10.0);
lib_basic->refresh ();
EXPECT_EQ (pie->bbox ().to_string (), "(0,-9000;9000,0)");
EXPECT_EQ (pie->get_display_name (), "Basic.PIE(l=1/0,r=9,a=-90..0,n=64)");
EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_handle1].to_string (), "0,-9");
EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_handle2].to_string (), "9,0");
EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_actual_handle1].to_string (), "0,-9");
EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_actual_handle2].to_string (), "9,0");
EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_radius].to_double (), 9.0);
EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_actual_radius].to_double (), 9.0);
EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_start_angle].to_double (), -90);
EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_actual_start_angle].to_double (), -90);
EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_end_angle].to_double (), 0);
EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_actual_end_angle].to_double (), 0);
// change end angle explicitly
plist = ly.get_pcell_parameters (pie->cell_index ());
plist[p_actual_end_angle] = 90.0;
pie = &ly.cell (ly.get_pcell_variant_cell (pie->cell_index (), plist));
// as the end angle is an input parameter, only after Library::refresh the other parameters get updated
EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_end_angle].to_double (), 0.0);
lib_basic->refresh ();
EXPECT_EQ (pie->bbox ().to_string (), "(0,-9000;9000,9000)");
EXPECT_EQ (pie->get_display_name (), "Basic.PIE(l=1/0,r=9,a=-90..90,n=64)");
EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_handle1].to_string (), "0,-9");
EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_handle2].to_string (), "0,9");
EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_actual_handle1].to_string (), "0,-9");
EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_actual_handle2].to_string (), "0,9");
EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_radius].to_double (), 9.0);
EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_actual_radius].to_double (), 9.0);
EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_start_angle].to_double (), -90);
EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_actual_start_angle].to_double (), -90);
EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_end_angle].to_double (), 90);
EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_actual_end_angle].to_double (), 90);
// change start angle explicitly
plist = ly.get_pcell_parameters (pie->cell_index ());
plist[p_actual_start_angle] = 0.0;
pie = &ly.cell (ly.get_pcell_variant_cell (pie->cell_index (), plist));
// as the end angle is an input parameter, only after Library::refresh the other parameters get updated
EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_start_angle].to_double (), -90.0);
lib_basic->refresh ();
EXPECT_EQ (pie->bbox ().to_string (), "(0,0;9000,9000)");
EXPECT_EQ (pie->get_display_name (), "Basic.PIE(l=1/0,r=9,a=0..90,n=64)");
EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_handle1].to_string (), "9,0");
EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_handle2].to_string (), "0,9");
EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_actual_handle1].to_string (), "9,0");
EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_actual_handle2].to_string (), "0,9");
EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_radius].to_double (), 9.0);
EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_actual_radius].to_double (), 9.0);
EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_start_angle].to_double (), 0);
EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_actual_start_angle].to_double (), 0);
EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_end_angle].to_double (), 90);
EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_actual_end_angle].to_double (), 90);
// change handle1 explicitly
plist = ly.get_pcell_parameters (pie->cell_index ());
plist[p_actual_handle1] = db::DPoint (0.0, -5.0);
pie = &ly.cell (ly.get_pcell_variant_cell (pie->cell_index (), plist));
// as the handle is an input parameter, only after Library::refresh the other parameters get updated
EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_start_angle].to_double (), 0.0);
lib_basic->refresh ();
EXPECT_EQ (pie->bbox ().to_string (), "(0,-9000;9000,9000)");
EXPECT_EQ (pie->get_display_name (), "Basic.PIE(l=1/0,r=9,a=-90..90,n=64)");
EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_handle1].to_string (), "0,-5");
EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_handle2].to_string (), "0,9");
EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_actual_handle1].to_string (), "0,-5");
EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_actual_handle2].to_string (), "0,9");
EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_start_angle].to_double (), -90.0);
EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_actual_start_angle].to_double (), -90.0);
EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_end_angle].to_double (), 90);
EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_actual_end_angle].to_double (), 90);
EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_radius].to_double (), 9);
EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_actual_radius].to_double (), 9);
// change handle2 explicitly
plist = ly.get_pcell_parameters (pie->cell_index ());
plist[p_actual_handle2] = db::DPoint (5.0, 0.0);
pie = &ly.cell (ly.get_pcell_variant_cell (pie->cell_index (), plist));
// as the handle is an input parameter, only after Library::refresh the other parameters get updated
EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_end_angle].to_double (), 90.0);
lib_basic->refresh ();
EXPECT_EQ (pie->bbox ().to_string (), "(0,-5000;5000,0)");
EXPECT_EQ (pie->get_display_name (), "Basic.PIE(l=1/0,r=5,a=-90..0,n=64)");
EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_handle1].to_string (), "0,-5");
EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_handle2].to_string (), "5,0");
EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_actual_handle1].to_string (), "0,-5");
EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_actual_handle2].to_string (), "5,0");
EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_start_angle].to_double (), -90.0);
EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_actual_start_angle].to_double (), -90.0);
EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_end_angle].to_double (), 0);
EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_actual_end_angle].to_double (), 0);
EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_radius].to_double (), 5);
EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_actual_radius].to_double (), 5);
}
TEST(3_Arc)
{
static size_t p_layer = 0;
static size_t p_radius1 = 1;
static size_t p_radius2 = 2;
static size_t p_start_angle = 3;
static size_t p_end_angle = 4;
static size_t p_handle1 = 5;
static size_t p_handle2 = 6;
static size_t p_npoints = 7;
static size_t p_actual_radius1 = 8;
static size_t p_actual_radius2 = 9;
static size_t p_actual_start_angle = 10;
static size_t p_actual_end_angle = 11;
static size_t p_actual_handle1 = 12;
static size_t p_actual_handle2 = 13;
static size_t p_total = 14;
db::Library *lib_basic = db::LibraryManager::instance ().lib_ptr_by_name ("Basic");
tl_assert (lib_basic);
db::Layout ly;
std::pair<bool, db::pcell_id_type> pc = lib_basic->layout ().pcell_by_name ("ARC");
tl_assert (pc.first);
std::map<std::string, tl::Variant> params;
params["layer"] = db::LayerProperties (1, 0);
params["actual_radius1"] = 4.0;
params["actual_radius2"] = 10.0;
params["actual_start_angle"] = -90.0;
params["actual_end_angle"] = 0.0;
db::cell_index_type lib_cell;
db::Cell *arc;
std::vector<tl::Variant> plist;
lib_cell = lib_basic->layout ().get_pcell_variant_dict (pc.second, params);
arc = &ly.cell (ly.get_lib_proxy (lib_basic, lib_cell));
// change radius explicitly
// has radius 10um, but bbox isn't correct for now (because handle was not updated)
EXPECT_EQ (arc->bbox ().to_string (), "(0,-10000;10000,1000)");
EXPECT_EQ (arc->get_display_name (), "Basic.ARC(l=1/0,r=4..10,a=-90..0,n=64)");
// only after Library::refresh the parameters get updated and bbox is correct
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_radius1].to_double (), 0.0);
lib_basic->refresh ();
EXPECT_EQ (arc->bbox ().to_string (), "(0,-10000;10000,0)");
EXPECT_EQ (arc->get_display_name (), "Basic.ARC(l=1/0,r=4..10,a=-90..0,n=64)");
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_radius1].to_double (), 4.0);
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_actual_radius1].to_double (), 4.0);
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_radius2].to_double (), 10.0);
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_actual_radius2].to_double (), 10.0);
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_start_angle].to_double (), -90);
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_actual_start_angle].to_double (), -90);
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_end_angle].to_double (), 0);
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_actual_end_angle].to_double (), 0);
// change radius2 explicitly
plist = ly.get_pcell_parameters (arc->cell_index ());
plist[p_actual_radius2] = 9.0;
arc = &ly.cell (ly.get_pcell_variant_cell (arc->cell_index (), plist));
// as the radius is an input parameter, only after Library::refresh the other parameters get updated
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_radius2].to_double (), 10.0);
lib_basic->refresh ();
EXPECT_EQ (arc->bbox ().to_string (), "(0,-9000;9000,0)");
EXPECT_EQ (arc->get_display_name (), "Basic.ARC(l=1/0,r=4..9,a=-90..0,n=64)");
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_handle1].to_string (), "0,-4");
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_handle2].to_string (), "9,0");
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_actual_handle1].to_string (), "0,-4");
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_actual_handle2].to_string (), "9,0");
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_radius1].to_double (), 4.0);
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_actual_radius1].to_double (), 4.0);
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_radius2].to_double (), 9.0);
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_actual_radius2].to_double (), 9.0);
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_start_angle].to_double (), -90);
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_actual_start_angle].to_double (), -90);
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_end_angle].to_double (), 0);
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_actual_end_angle].to_double (), 0);
// change radius1 explicitly
plist = ly.get_pcell_parameters (arc->cell_index ());
plist[p_actual_radius1] = 5.0;
arc = &ly.cell (ly.get_pcell_variant_cell (arc->cell_index (), plist));
// as the radius is an input parameter, only after Library::refresh the other parameters get updated
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_radius1].to_double (), 4.0);
lib_basic->refresh ();
EXPECT_EQ (arc->bbox ().to_string (), "(0,-9000;9000,0)");
EXPECT_EQ (arc->get_display_name (), "Basic.ARC(l=1/0,r=5..9,a=-90..0,n=64)");
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_handle1].to_string (), "0,-5");
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_handle2].to_string (), "9,0");
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_actual_handle1].to_string (), "0,-5");
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_actual_handle2].to_string (), "9,0");
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_radius1].to_double (), 5.0);
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_actual_radius1].to_double (), 5.0);
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_radius2].to_double (), 9.0);
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_actual_radius2].to_double (), 9.0);
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_start_angle].to_double (), -90);
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_actual_start_angle].to_double (), -90);
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_end_angle].to_double (), 0);
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_actual_end_angle].to_double (), 0);
// change end angle explicitly
plist = ly.get_pcell_parameters (arc->cell_index ());
plist[p_actual_end_angle] = 90.0;
arc = &ly.cell (ly.get_pcell_variant_cell (arc->cell_index (), plist));
// as the end angle is an input parameter, only after Library::refresh the other parameters get updated
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_end_angle].to_double (), 0.0);
lib_basic->refresh ();
EXPECT_EQ (arc->bbox ().to_string (), "(0,-9000;9000,9000)");
EXPECT_EQ (arc->get_display_name (), "Basic.ARC(l=1/0,r=5..9,a=-90..90,n=64)");
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_handle1].to_string (), "0,-5");
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_handle2].to_string (), "0,9");
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_actual_handle1].to_string (), "0,-5");
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_actual_handle2].to_string (), "0,9");
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_radius1].to_double (), 5.0);
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_actual_radius1].to_double (), 5.0);
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_radius2].to_double (), 9.0);
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_actual_radius2].to_double (), 9.0);
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_start_angle].to_double (), -90);
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_actual_start_angle].to_double (), -90);
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_end_angle].to_double (), 90);
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_actual_end_angle].to_double (), 90);
// change start angle explicitly
plist = ly.get_pcell_parameters (arc->cell_index ());
plist[p_actual_start_angle] = 0.0;
arc = &ly.cell (ly.get_pcell_variant_cell (arc->cell_index (), plist));
// as the end angle is an input parameter, only after Library::refresh the other parameters get updated
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_start_angle].to_double (), -90.0);
lib_basic->refresh ();
EXPECT_EQ (arc->bbox ().to_string (), "(0,0;9000,9000)");
EXPECT_EQ (arc->get_display_name (), "Basic.ARC(l=1/0,r=5..9,a=0..90,n=64)");
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_handle1].to_string (), "5,0");
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_handle2].to_string (), "0,9");
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_actual_handle1].to_string (), "5,0");
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_actual_handle2].to_string (), "0,9");
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_radius1].to_double (), 5.0);
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_actual_radius1].to_double (), 5.0);
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_radius2].to_double (), 9.0);
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_actual_radius2].to_double (), 9.0);
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_start_angle].to_double (), 0);
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_actual_start_angle].to_double (), 0);
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_end_angle].to_double (), 90);
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_actual_end_angle].to_double (), 90);
// change handle1 explicitly
plist = ly.get_pcell_parameters (arc->cell_index ());
plist[p_actual_handle1] = db::DPoint (0.0, -5.0);
arc = &ly.cell (ly.get_pcell_variant_cell (arc->cell_index (), plist));
// as the handle is an input parameter, only after Library::refresh the other parameters get updated
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_start_angle].to_double (), 0.0);
lib_basic->refresh ();
EXPECT_EQ (arc->bbox ().to_string (), "(0,-9000;9000,9000)");
EXPECT_EQ (arc->get_display_name (), "Basic.ARC(l=1/0,r=5..9,a=-90..90,n=64)");
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_handle1].to_string (), "0,-5");
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_handle2].to_string (), "0,9");
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_actual_handle1].to_string (), "0,-5");
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_actual_handle2].to_string (), "0,9");
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_start_angle].to_double (), -90.0);
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_actual_start_angle].to_double (), -90.0);
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_end_angle].to_double (), 90);
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_actual_end_angle].to_double (), 90);
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_radius1].to_double (), 5);
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_actual_radius1].to_double (), 5);
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_radius2].to_double (), 9);
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_actual_radius2].to_double (), 9);
// change handle2 explicitly
plist = ly.get_pcell_parameters (arc->cell_index ());
plist[p_actual_handle2] = db::DPoint (9.0, 0.0);
arc = &ly.cell (ly.get_pcell_variant_cell (arc->cell_index (), plist));
// as the handle is an input parameter, only after Library::refresh the other parameters get updated
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_end_angle].to_double (), 90.0);
lib_basic->refresh ();
EXPECT_EQ (arc->bbox ().to_string (), "(0,-9000;9000,0)");
EXPECT_EQ (arc->get_display_name (), "Basic.ARC(l=1/0,r=5..9,a=-90..0,n=64)");
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_handle1].to_string (), "0,-5");
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_handle2].to_string (), "9,0");
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_actual_handle1].to_string (), "0,-5");
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_actual_handle2].to_string (), "9,0");
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_start_angle].to_double (), -90.0);
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_actual_start_angle].to_double (), -90.0);
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_end_angle].to_double (), 0);
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_actual_end_angle].to_double (), 0);
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_radius1].to_double (), 5);
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_actual_radius1].to_double (), 5);
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_radius2].to_double (), 9);
EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_actual_radius2].to_double (), 9);
}
TEST(4_Donut)
{
static size_t p_layer = 0;
static size_t p_radius1 = 1;
static size_t p_radius2 = 2;
static size_t p_handle1 = 3;
static size_t p_handle2 = 4;
static size_t p_npoints = 5;
static size_t p_actual_radius1 = 6;
static size_t p_actual_radius2 = 7;
static size_t p_total = 8;
db::Library *lib_basic = db::LibraryManager::instance ().lib_ptr_by_name ("Basic");
tl_assert (lib_basic);
db::Layout ly;
std::pair<bool, db::pcell_id_type> pc = lib_basic->layout ().pcell_by_name ("DONUT");
tl_assert (pc.first);
std::map<std::string, tl::Variant> params;
params["layer"] = db::LayerProperties (1, 0);
params["actual_radius1"] = 4.0;
params["actual_radius2"] = 10.0;
params["actual_start_angle"] = -90.0;
params["actual_end_angle"] = 0.0;
db::cell_index_type lib_cell;
db::Cell *donut;
std::vector<tl::Variant> plist;
lib_cell = lib_basic->layout ().get_pcell_variant_dict (pc.second, params);
donut = &ly.cell (ly.get_lib_proxy (lib_basic, lib_cell));
// change radius explicitly
// has radius 10um, but bbox isn't correct for now (because handle was not updated)
EXPECT_EQ (donut->bbox ().to_string (), "(-10000,-10000;10000,10000)");
EXPECT_EQ (donut->get_display_name (), "Basic.DONUT(l=1/0,r=4..10,n=64)");
// only after Library::refresh the parameters get updated and bbox is correct
EXPECT_EQ (ly.get_pcell_parameters (donut->cell_index ()) [p_radius1].to_double (), 0.0);
lib_basic->refresh ();
EXPECT_EQ (donut->bbox ().to_string (), "(-10000,-10000;10000,10000)");
EXPECT_EQ (donut->get_display_name (), "Basic.DONUT(l=1/0,r=4..10,n=64)");
EXPECT_EQ (ly.get_pcell_parameters (donut->cell_index ()) [p_radius1].to_double (), 4.0);
EXPECT_EQ (ly.get_pcell_parameters (donut->cell_index ()) [p_actual_radius1].to_double (), 4.0);
EXPECT_EQ (ly.get_pcell_parameters (donut->cell_index ()) [p_radius2].to_double (), 10.0);
EXPECT_EQ (ly.get_pcell_parameters (donut->cell_index ()) [p_actual_radius2].to_double (), 10.0);
// change radius2 explicitly
plist = ly.get_pcell_parameters (donut->cell_index ());
plist[p_actual_radius2] = 9.0;
donut = &ly.cell (ly.get_pcell_variant_cell (donut->cell_index (), plist));
// as the radius is an input parameter, only after Library::refresh the other parameters get updated
EXPECT_EQ (ly.get_pcell_parameters (donut->cell_index ()) [p_radius2].to_double (), 10.0);
lib_basic->refresh ();
EXPECT_EQ (donut->bbox ().to_string (), "(-9000,-9000;9000,9000)");
EXPECT_EQ (donut->get_display_name (), "Basic.DONUT(l=1/0,r=4..9,n=64)");
EXPECT_EQ (ly.get_pcell_parameters (donut->cell_index ()) [p_handle1].to_string (), "-4,0");
EXPECT_EQ (ly.get_pcell_parameters (donut->cell_index ()) [p_handle2].to_string (), "-9,0");
EXPECT_EQ (ly.get_pcell_parameters (donut->cell_index ()) [p_radius1].to_double (), 4.0);
EXPECT_EQ (ly.get_pcell_parameters (donut->cell_index ()) [p_actual_radius1].to_double (), 4.0);
EXPECT_EQ (ly.get_pcell_parameters (donut->cell_index ()) [p_radius2].to_double (), 9.0);
EXPECT_EQ (ly.get_pcell_parameters (donut->cell_index ()) [p_actual_radius2].to_double (), 9.0);
// change radius1 explicitly
plist = ly.get_pcell_parameters (donut->cell_index ());
plist[p_actual_radius1] = 5.0;
donut = &ly.cell (ly.get_pcell_variant_cell (donut->cell_index (), plist));
// as the radius is an input parameter, only after Library::refresh the other parameters get updated
EXPECT_EQ (ly.get_pcell_parameters (donut->cell_index ()) [p_radius1].to_double (), 4.0);
lib_basic->refresh ();
EXPECT_EQ (donut->bbox ().to_string (), "(-9000,-9000;9000,9000)");
EXPECT_EQ (donut->get_display_name (), "Basic.DONUT(l=1/0,r=5..9,n=64)");
EXPECT_EQ (ly.get_pcell_parameters (donut->cell_index ()) [p_handle1].to_string (), "-5,0");
EXPECT_EQ (ly.get_pcell_parameters (donut->cell_index ()) [p_handle2].to_string (), "-9,0");
EXPECT_EQ (ly.get_pcell_parameters (donut->cell_index ()) [p_radius1].to_double (), 5.0);
EXPECT_EQ (ly.get_pcell_parameters (donut->cell_index ()) [p_actual_radius1].to_double (), 5.0);
EXPECT_EQ (ly.get_pcell_parameters (donut->cell_index ()) [p_radius2].to_double (), 9.0);
EXPECT_EQ (ly.get_pcell_parameters (donut->cell_index ()) [p_actual_radius2].to_double (), 9.0);
// change handle1 explicitly
plist = ly.get_pcell_parameters (donut->cell_index ());
plist[p_handle1] = db::DPoint (0.0, -5.0);
donut = &ly.cell (ly.get_pcell_variant_cell (donut->cell_index (), plist));
lib_basic->refresh ();
EXPECT_EQ (donut->bbox ().to_string (), "(-9000,-9000;9000,9000)");
EXPECT_EQ (donut->get_display_name (), "Basic.DONUT(l=1/0,r=5..9,n=64)");
EXPECT_EQ (ly.get_pcell_parameters (donut->cell_index ()) [p_handle1].to_string (), "0,-5");
EXPECT_EQ (ly.get_pcell_parameters (donut->cell_index ()) [p_handle2].to_string (), "-9,0");
EXPECT_EQ (ly.get_pcell_parameters (donut->cell_index ()) [p_radius1].to_double (), 5);
EXPECT_EQ (ly.get_pcell_parameters (donut->cell_index ()) [p_actual_radius1].to_double (), 5);
EXPECT_EQ (ly.get_pcell_parameters (donut->cell_index ()) [p_radius2].to_double (), 9);
EXPECT_EQ (ly.get_pcell_parameters (donut->cell_index ()) [p_actual_radius2].to_double (), 9);
// change handle2 explicitly
plist = ly.get_pcell_parameters (donut->cell_index ());
plist[p_handle2] = db::DPoint (9.0, 0.0);
donut = &ly.cell (ly.get_pcell_variant_cell (donut->cell_index (), plist));
lib_basic->refresh ();
EXPECT_EQ (donut->bbox ().to_string (), "(-9000,-9000;9000,9000)");
EXPECT_EQ (donut->get_display_name (), "Basic.DONUT(l=1/0,r=5..9,n=64)");
EXPECT_EQ (ly.get_pcell_parameters (donut->cell_index ()) [p_handle1].to_string (), "0,-5");
EXPECT_EQ (ly.get_pcell_parameters (donut->cell_index ()) [p_handle2].to_string (), "9,0");
EXPECT_EQ (ly.get_pcell_parameters (donut->cell_index ()) [p_radius1].to_double (), 5);
EXPECT_EQ (ly.get_pcell_parameters (donut->cell_index ()) [p_actual_radius1].to_double (), 5);
EXPECT_EQ (ly.get_pcell_parameters (donut->cell_index ()) [p_radius2].to_double (), 9);
EXPECT_EQ (ly.get_pcell_parameters (donut->cell_index ()) [p_actual_radius2].to_double (), 9);
unsigned int l1 = ly.get_layer (db::LayerProperties (1, 0));
db::Shapes shapes;
db::Shape s = shapes.insert (db::Box (1000, 2000, 3000, 5000));
EXPECT_EQ (lib_basic->layout ().pcell_declaration (pc.second)->can_create_from_shape (ly, s, l1), true);
EXPECT_EQ (lib_basic->layout ().pcell_declaration (pc.second)->transformation_from_shape (ly, s, l1).to_string (), "r0 2000,3500");
plist = lib_basic->layout ().pcell_declaration (pc.second)->parameters_from_shape (ly, s, l1);
EXPECT_EQ (plist [p_layer].to_string (), "1/0");
EXPECT_EQ (plist [p_actual_radius1].to_string (), "1");
EXPECT_EQ (plist [p_actual_radius2].to_string (), "0.5");
}
TEST(5_Ellipse)
{
static size_t p_layer = 0;
static size_t p_radius_x = 1;
static size_t p_radius_y = 2;
static size_t p_handle_x = 3;
static size_t p_handle_y = 4;
static size_t p_npoints = 5;
static size_t p_actual_radius_x = 6;
static size_t p_actual_radius_y = 7;
static size_t p_total = 8;
db::Library *lib_basic = db::LibraryManager::instance ().lib_ptr_by_name ("Basic");
tl_assert (lib_basic);
db::Layout ly;
std::pair<bool, db::pcell_id_type> pc = lib_basic->layout ().pcell_by_name ("ELLIPSE");
tl_assert (pc.first);
std::map<std::string, tl::Variant> params;
params["layer"] = db::LayerProperties (1, 0);
params["actual_radius_x"] = 4.0;
params["actual_radius_y"] = 10.0;
params["actual_start_angle"] = -90.0;
params["actual_end_angle"] = 0.0;
db::cell_index_type lib_cell;
db::Cell *ellipse;
std::vector<tl::Variant> plist;
lib_cell = lib_basic->layout ().get_pcell_variant_dict (pc.second, params);
ellipse = &ly.cell (ly.get_lib_proxy (lib_basic, lib_cell));
// change radius explicitly
// has radius 10um, but bbox isn't correct for now (because handle was not updated)
EXPECT_EQ (ellipse->bbox ().to_string (), "(-4000,-10000;4000,10000)");
EXPECT_EQ (ellipse->get_display_name (), "Basic.ELLIPSE(l=1/0,rx=4,ry=10,n=64)");
// only after Library::refresh the parameters get updated and bbox is correct
EXPECT_EQ (ly.get_pcell_parameters (ellipse->cell_index ()) [p_radius_x].to_double (), 0.0);
lib_basic->refresh ();
EXPECT_EQ (ellipse->bbox ().to_string (), "(-4000,-10000;4000,10000)");
EXPECT_EQ (ellipse->get_display_name (), "Basic.ELLIPSE(l=1/0,rx=4,ry=10,n=64)");
EXPECT_EQ (ly.get_pcell_parameters (ellipse->cell_index ()) [p_radius_x].to_double (), 4.0);
EXPECT_EQ (ly.get_pcell_parameters (ellipse->cell_index ()) [p_actual_radius_x].to_double (), 4.0);
EXPECT_EQ (ly.get_pcell_parameters (ellipse->cell_index ()) [p_radius_y].to_double (), 10.0);
EXPECT_EQ (ly.get_pcell_parameters (ellipse->cell_index ()) [p_actual_radius_y].to_double (), 10.0);
// change radius2 explicitly
plist = ly.get_pcell_parameters (ellipse->cell_index ());
plist[p_actual_radius_y] = 9.0;
ellipse = &ly.cell (ly.get_pcell_variant_cell (ellipse->cell_index (), plist));
// as the radius is an input parameter, only after Library::refresh the other parameters get updated
EXPECT_EQ (ly.get_pcell_parameters (ellipse->cell_index ()) [p_radius_y].to_double (), 10.0);
lib_basic->refresh ();
EXPECT_EQ (ellipse->bbox ().to_string (), "(-4000,-9000;4000,9000)");
EXPECT_EQ (ellipse->get_display_name (), "Basic.ELLIPSE(l=1/0,rx=4,ry=9,n=64)");
EXPECT_EQ (ly.get_pcell_parameters (ellipse->cell_index ()) [p_handle_x].to_string (), "-4,0");
EXPECT_EQ (ly.get_pcell_parameters (ellipse->cell_index ()) [p_handle_y].to_string (), "0,9");
EXPECT_EQ (ly.get_pcell_parameters (ellipse->cell_index ()) [p_radius_x].to_double (), 4.0);
EXPECT_EQ (ly.get_pcell_parameters (ellipse->cell_index ()) [p_actual_radius_x].to_double (), 4.0);
EXPECT_EQ (ly.get_pcell_parameters (ellipse->cell_index ()) [p_radius_y].to_double (), 9.0);
EXPECT_EQ (ly.get_pcell_parameters (ellipse->cell_index ()) [p_actual_radius_y].to_double (), 9.0);
// change radius1 explicitly
plist = ly.get_pcell_parameters (ellipse->cell_index ());
plist[p_actual_radius_x] = 5.0;
ellipse = &ly.cell (ly.get_pcell_variant_cell (ellipse->cell_index (), plist));
// as the radius is an input parameter, only after Library::refresh the other parameters get updated
EXPECT_EQ (ly.get_pcell_parameters (ellipse->cell_index ()) [p_radius_x].to_double (), 4.0);
lib_basic->refresh ();
EXPECT_EQ (ellipse->bbox ().to_string (), "(-5000,-9000;5000,9000)");
EXPECT_EQ (ellipse->get_display_name (), "Basic.ELLIPSE(l=1/0,rx=5,ry=9,n=64)");
EXPECT_EQ (ly.get_pcell_parameters (ellipse->cell_index ()) [p_handle_x].to_string (), "-5,0");
EXPECT_EQ (ly.get_pcell_parameters (ellipse->cell_index ()) [p_handle_y].to_string (), "0,9");
EXPECT_EQ (ly.get_pcell_parameters (ellipse->cell_index ()) [p_radius_x].to_double (), 5.0);
EXPECT_EQ (ly.get_pcell_parameters (ellipse->cell_index ()) [p_actual_radius_x].to_double (), 5.0);
EXPECT_EQ (ly.get_pcell_parameters (ellipse->cell_index ()) [p_radius_y].to_double (), 9.0);
EXPECT_EQ (ly.get_pcell_parameters (ellipse->cell_index ()) [p_actual_radius_y].to_double (), 9.0);
// change handle1 explicitly
plist = ly.get_pcell_parameters (ellipse->cell_index ());
plist[p_handle_x] = db::DPoint (-5.0, 0.0);
ellipse = &ly.cell (ly.get_pcell_variant_cell (ellipse->cell_index (), plist));
lib_basic->refresh ();
EXPECT_EQ (ellipse->bbox ().to_string (), "(-5000,-9000;5000,9000)");
EXPECT_EQ (ellipse->get_display_name (), "Basic.ELLIPSE(l=1/0,rx=5,ry=9,n=64)");
EXPECT_EQ (ly.get_pcell_parameters (ellipse->cell_index ()) [p_handle_x].to_string (), "-5,0");
EXPECT_EQ (ly.get_pcell_parameters (ellipse->cell_index ()) [p_handle_y].to_string (), "0,9");
EXPECT_EQ (ly.get_pcell_parameters (ellipse->cell_index ()) [p_radius_x].to_double (), 5);
EXPECT_EQ (ly.get_pcell_parameters (ellipse->cell_index ()) [p_actual_radius_x].to_double (), 5);
EXPECT_EQ (ly.get_pcell_parameters (ellipse->cell_index ()) [p_radius_y].to_double (), 9);
EXPECT_EQ (ly.get_pcell_parameters (ellipse->cell_index ()) [p_actual_radius_y].to_double (), 9);
// change handle2 explicitly
plist = ly.get_pcell_parameters (ellipse->cell_index ());
plist[p_handle_y] = db::DPoint (0.0, 9.0);
ellipse = &ly.cell (ly.get_pcell_variant_cell (ellipse->cell_index (), plist));
lib_basic->refresh ();
EXPECT_EQ (ellipse->bbox ().to_string (), "(-5000,-9000;5000,9000)");
EXPECT_EQ (ellipse->get_display_name (), "Basic.ELLIPSE(l=1/0,rx=5,ry=9,n=64)");
EXPECT_EQ (ly.get_pcell_parameters (ellipse->cell_index ()) [p_handle_x].to_string (), "-5,0");
EXPECT_EQ (ly.get_pcell_parameters (ellipse->cell_index ()) [p_handle_y].to_string (), "0,9");
EXPECT_EQ (ly.get_pcell_parameters (ellipse->cell_index ()) [p_radius_x].to_double (), 5);
EXPECT_EQ (ly.get_pcell_parameters (ellipse->cell_index ()) [p_actual_radius_x].to_double (), 5);
EXPECT_EQ (ly.get_pcell_parameters (ellipse->cell_index ()) [p_radius_y].to_double (), 9);
EXPECT_EQ (ly.get_pcell_parameters (ellipse->cell_index ()) [p_actual_radius_y].to_double (), 9);
unsigned int l1 = ly.get_layer (db::LayerProperties (1, 0));
db::Shapes shapes;
db::Shape s = shapes.insert (db::Box (1000, 2000, 3000, 5000));
EXPECT_EQ (lib_basic->layout ().pcell_declaration (pc.second)->can_create_from_shape (ly, s, l1), true);
EXPECT_EQ (lib_basic->layout ().pcell_declaration (pc.second)->transformation_from_shape (ly, s, l1).to_string (), "r0 2000,3500");
plist = lib_basic->layout ().pcell_declaration (pc.second)->parameters_from_shape (ly, s, l1);
EXPECT_EQ (plist [p_layer].to_string (), "1/0");
EXPECT_EQ (plist [p_actual_radius_x].to_string (), "1");
EXPECT_EQ (plist [p_actual_radius_y].to_string (), "1.5");
}
// regeneration of PCells after reading
TEST(10)
{
db::Layout ly;
{
std::string fn (tl::testdata ());
fn += "/gds/basic_instances.gds";
tl::InputStream stream (fn);
db::Reader reader (stream);
reader.read (ly);
}
db::Library *lib_basic = db::LibraryManager::instance ().lib_ptr_by_name ("Basic");
tl_assert (lib_basic);
lib_basic->refresh ();
CHECKPOINT();
db::compare_layouts (_this, ly, tl::testdata () + "/gds/basic_instances_au.gds");
}

View File

@ -118,12 +118,14 @@ GDS2WriterOptionPage::multi_xy_clicked ()
// ---------------------------------------------------------------
// GDS2WriterPluginDeclaration definition and implementation
class GDS2WriterPluginDeclaration
namespace {
class GDS2WriterPluginDeclarationBase
: public StreamWriterPluginDeclaration
{
public:
GDS2WriterPluginDeclaration ()
: StreamWriterPluginDeclaration (db::GDS2WriterOptions ().format_name ())
GDS2WriterPluginDeclarationBase (const std::string &name)
: StreamWriterPluginDeclaration (name)
{
// .. nothing yet ..
}
@ -152,21 +154,47 @@ public:
}
};
}
/**
* @brief A dummy plugin for GDS2Text
* @brief A plugin for GDS2
*/
class GDS2WriterPluginDeclaration
: public GDS2WriterPluginDeclarationBase
{
public:
GDS2WriterPluginDeclaration ()
: GDS2WriterPluginDeclarationBase (db::GDS2WriterOptions ().format_name ())
{
// .. nothing yet ..
}
};
/**
* @brief A plugin for GDS2Text
*
* GDS2Text shares the options with GDS2, although some limitations do not exist.
* There is not specific option set for GDS2Text. The writer will take the options from GDS2.
*/
class GDS2TextWriterPluginDeclaration
: public StreamWriterPluginDeclaration
: public GDS2WriterPluginDeclarationBase
{
public:
GDS2TextWriterPluginDeclaration ()
: StreamWriterPluginDeclaration ("GDS2Text")
: GDS2WriterPluginDeclarationBase ("GDS2Text")
{
// .. nothing yet ..
}
virtual const char *options_alias () const
{
return db::GDS2WriterOptions ().format_name ().c_str ();
}
StreamWriterOptionsPage *format_specific_options_page (QWidget *) const
{
return 0;
}
};
static tl::RegisteredClass<lay::PluginDeclaration> plugin_decl1 (new lay::GDS2WriterPluginDeclaration (), 10000, "GDS2Writer");

BIN
testdata/gds/basic_instances.gds vendored Normal file

Binary file not shown.

BIN
testdata/gds/basic_instances_au.gds vendored Normal file

Binary file not shown.

View File

@ -110,6 +110,7 @@ if RBA.constants.member?(:PCellDeclarationHelper)
param("layer", BoxPCell2::TypeLayer, "Layer", :default => RBA::LayerInfo::new(0, 0))
param("width", BoxPCell2::TypeDouble, "Width", :default => 1.0)
param("height", BoxPCell2::TypeDouble, "Height", :default => 1.0)
param("secret", BoxPCell2::TypeInt, "Secret", :default => 0)
end
@ -130,6 +131,10 @@ if RBA.constants.member?(:PCellDeclarationHelper)
end
def coerce_parameters_impl
self.secret = [0, self.secret].max
end
def can_create_from_shape_impl
return self.shape.is_box?
end
@ -192,150 +197,145 @@ class DBPCell_TestClass < TestBase
# instantiate and register the library
tl = PCellTestLib::new
begin
ly = RBA::Layout::new(true)
ly.dbu = 0.01
ly = RBA::Layout::new(true)
ly.dbu = 0.01
li1 = ly.layer(1, 0)
li1 = ly.layer(1, 0)
ci1 = ly.add_cell("c1")
c1 = ly.cell(ci1)
ci1 = ly.add_cell("c1")
c1 = ly.cell(ci1)
lib = RBA::Library::library_by_name("NoLib")
assert_equal(lib == nil, true)
lib = RBA::Library::library_by_name("PCellTestLib")
assert_equal(lib != nil, true)
pcell_decl = lib.layout.pcell_declaration("x")
assert_equal(pcell_decl == nil, true)
pcell_decl = lib.layout.pcell_declaration("Box")
assert_equal(pcell_decl != nil, true)
pcell_decl_id = lib.layout.pcell_id("Box")
assert_equal(pcell_decl.id, pcell_decl_id)
assert_equal(lib.layout.pcell_names.join(":"), "Box")
assert_equal(lib.layout.pcell_ids, [ pcell_decl_id ])
assert_equal(lib.layout.pcell_declaration(pcell_decl_id).id, pcell_decl_id)
lib = RBA::Library::library_by_name("NoLib")
assert_equal(lib == nil, true)
lib = RBA::Library::library_by_name("PCellTestLib")
assert_equal(lib != nil, true)
pcell_decl = lib.layout.pcell_declaration("x")
assert_equal(pcell_decl == nil, true)
pcell_decl = lib.layout.pcell_declaration("Box")
assert_equal(pcell_decl != nil, true)
pcell_decl_id = lib.layout.pcell_id("Box")
assert_equal(pcell_decl.id, pcell_decl_id)
assert_equal(lib.layout.pcell_names.join(":"), "Box")
assert_equal(lib.layout.pcell_ids, [ pcell_decl_id ])
assert_equal(lib.layout.pcell_declaration(pcell_decl_id).id, pcell_decl_id)
param = [ RBA::LayerInfo::new(1, 0) ] # rest is filled with defaults
pcell_var_id = ly.add_pcell_variant(lib, pcell_decl_id, param)
pcell_var = ly.cell(pcell_var_id)
pcell_inst = c1.insert(RBA::CellInstArray::new(pcell_var_id, RBA::Trans::new))
assert_equal(pcell_var.layout.inspect, ly.inspect)
assert_equal(pcell_var.library.inspect, lib.inspect)
assert_equal(pcell_var.is_pcell_variant?, true)
assert_equal(pcell_var.display_title, "PCellTestLib.Box(L=1/0,W=1.000,H=1.000)")
assert_equal(pcell_var.basic_name, "Box")
assert_equal(c1.is_pcell_variant?, false)
assert_equal(c1.is_pcell_variant?(pcell_inst), true)
assert_equal(pcell_var.pcell_id, pcell_decl_id)
assert_equal(pcell_var.pcell_library.inspect, lib.inspect)
assert_equal(pcell_var.pcell_parameters.inspect, "[<1/0>, 1.0, 1.0]")
assert_equal(norm_hash(pcell_var.pcell_parameters_by_name), "{\"h\"=>1.0, \"l\"=><1/0>, \"w\"=>1.0}")
assert_equal(pcell_var.pcell_parameter("h").inspect, "1.0")
assert_equal(c1.pcell_parameters(pcell_inst).inspect, "[<1/0>, 1.0, 1.0]")
assert_equal(norm_hash(c1.pcell_parameters_by_name(pcell_inst)), "{\"h\"=>1.0, \"l\"=><1/0>, \"w\"=>1.0}")
assert_equal(c1.pcell_parameter(pcell_inst, "h").inspect, "1.0")
assert_equal(norm_hash(pcell_inst.pcell_parameters_by_name), "{\"h\"=>1.0, \"l\"=><1/0>, \"w\"=>1.0}")
assert_equal(pcell_inst["h"].inspect, "1.0")
assert_equal(pcell_inst["i"].inspect, "nil")
assert_equal(pcell_inst.pcell_parameter("h").inspect, "1.0")
assert_equal(pcell_var.pcell_declaration.inspect, pcell_decl.inspect)
assert_equal(c1.pcell_declaration(pcell_inst).inspect, pcell_decl.inspect)
assert_equal(pcell_inst.pcell_declaration.inspect, pcell_decl.inspect)
param = [ RBA::LayerInfo::new(1, 0) ] # rest is filled with defaults
pcell_var_id = ly.add_pcell_variant(lib, pcell_decl_id, param)
pcell_var = ly.cell(pcell_var_id)
pcell_inst = c1.insert(RBA::CellInstArray::new(pcell_var_id, RBA::Trans::new))
assert_equal(pcell_var.layout.inspect, ly.inspect)
assert_equal(pcell_var.library.inspect, lib.inspect)
assert_equal(pcell_var.is_pcell_variant?, true)
assert_equal(pcell_var.display_title, "PCellTestLib.Box(L=1/0,W=1.000,H=1.000)")
assert_equal(pcell_var.basic_name, "Box")
assert_equal(c1.is_pcell_variant?, false)
assert_equal(c1.is_pcell_variant?(pcell_inst), true)
assert_equal(pcell_var.pcell_id, pcell_decl_id)
assert_equal(pcell_var.pcell_library.inspect, lib.inspect)
assert_equal(pcell_var.pcell_parameters.inspect, "[<1/0>, 1.0, 1.0]")
assert_equal(norm_hash(pcell_var.pcell_parameters_by_name), "{\"h\"=>1.0, \"l\"=><1/0>, \"w\"=>1.0}")
assert_equal(pcell_var.pcell_parameter("h").inspect, "1.0")
assert_equal(c1.pcell_parameters(pcell_inst).inspect, "[<1/0>, 1.0, 1.0]")
assert_equal(norm_hash(c1.pcell_parameters_by_name(pcell_inst)), "{\"h\"=>1.0, \"l\"=><1/0>, \"w\"=>1.0}")
assert_equal(c1.pcell_parameter(pcell_inst, "h").inspect, "1.0")
assert_equal(norm_hash(pcell_inst.pcell_parameters_by_name), "{\"h\"=>1.0, \"l\"=><1/0>, \"w\"=>1.0}")
assert_equal(pcell_inst["h"].inspect, "1.0")
assert_equal(pcell_inst["i"].inspect, "nil")
assert_equal(pcell_inst.pcell_parameter("h").inspect, "1.0")
assert_equal(pcell_var.pcell_declaration.inspect, pcell_decl.inspect)
assert_equal(c1.pcell_declaration(pcell_inst).inspect, pcell_decl.inspect)
assert_equal(pcell_inst.pcell_declaration.inspect, pcell_decl.inspect)
pcell_inst["h"] = 2.0
assert_equal(norm_hash(pcell_inst.pcell_parameters_by_name), "{\"h\"=>2.0, \"l\"=><1/0>, \"w\"=>1.0}")
pcell_inst["abc"] = "a property"
assert_equal(pcell_inst.property("abc").inspect, "\"a property\"")
pcell_inst["h"] = 2.0
assert_equal(norm_hash(pcell_inst.pcell_parameters_by_name), "{\"h\"=>2.0, \"l\"=><1/0>, \"w\"=>1.0}")
pcell_inst["abc"] = "a property"
assert_equal(pcell_inst.property("abc").inspect, "\"a property\"")
c1.clear
c1.clear
param = [ RBA::LayerInfo::new(1, 0), 5.0, 10.0 ]
pcell_var_id = ly.add_pcell_variant(lib, pcell_decl_id, param)
pcell_var = ly.cell(pcell_var_id)
pcell_inst = c1.insert(RBA::CellInstArray::new(pcell_var_id, RBA::Trans::new))
assert_equal(pcell_var.layout.inspect, ly.inspect)
assert_equal(pcell_var.library.inspect, lib.inspect)
assert_equal(pcell_var.is_pcell_variant?, true)
assert_equal(pcell_var.display_title, "PCellTestLib.Box(L=1/0,W=5.000,H=10.000)")
assert_equal(pcell_var.basic_name, "Box")
assert_equal(c1.is_pcell_variant?, false)
assert_equal(c1.is_pcell_variant?(pcell_inst), true)
assert_equal(pcell_var.pcell_id, pcell_decl_id)
assert_equal(pcell_var.pcell_library.inspect, lib.inspect)
assert_equal(pcell_var.pcell_parameters.inspect, "[<1/0>, 5.0, 10.0]")
assert_equal(c1.pcell_parameters(pcell_inst).inspect, "[<1/0>, 5.0, 10.0]")
assert_equal(pcell_inst.pcell_parameters.inspect, "[<1/0>, 5.0, 10.0]")
assert_equal(pcell_var.pcell_declaration.inspect, pcell_decl.inspect)
assert_equal(c1.pcell_declaration(pcell_inst).inspect, pcell_decl.inspect)
param = [ RBA::LayerInfo::new(1, 0), 5.0, 10.0 ]
pcell_var_id = ly.add_pcell_variant(lib, pcell_decl_id, param)
pcell_var = ly.cell(pcell_var_id)
pcell_inst = c1.insert(RBA::CellInstArray::new(pcell_var_id, RBA::Trans::new))
assert_equal(pcell_var.layout.inspect, ly.inspect)
assert_equal(pcell_var.library.inspect, lib.inspect)
assert_equal(pcell_var.is_pcell_variant?, true)
assert_equal(pcell_var.display_title, "PCellTestLib.Box(L=1/0,W=5.000,H=10.000)")
assert_equal(pcell_var.basic_name, "Box")
assert_equal(c1.is_pcell_variant?, false)
assert_equal(c1.is_pcell_variant?(pcell_inst), true)
assert_equal(pcell_var.pcell_id, pcell_decl_id)
assert_equal(pcell_var.pcell_library.inspect, lib.inspect)
assert_equal(pcell_var.pcell_parameters.inspect, "[<1/0>, 5.0, 10.0]")
assert_equal(c1.pcell_parameters(pcell_inst).inspect, "[<1/0>, 5.0, 10.0]")
assert_equal(pcell_inst.pcell_parameters.inspect, "[<1/0>, 5.0, 10.0]")
assert_equal(pcell_var.pcell_declaration.inspect, pcell_decl.inspect)
assert_equal(c1.pcell_declaration(pcell_inst).inspect, pcell_decl.inspect)
li1 = ly.layer_indices.find { |li| ly.get_info(li).to_s == "1/0" }
assert_equal(li1 != nil, true)
assert_equal(ly.is_valid_layer?(li1), true)
assert_equal(ly.get_info(li1).to_s, "1/0")
li1 = ly.layer_indices.find { |li| ly.get_info(li).to_s == "1/0" }
assert_equal(li1 != nil, true)
assert_equal(ly.is_valid_layer?(li1), true)
assert_equal(ly.get_info(li1).to_s, "1/0")
lib_proxy_id = ly.add_lib_cell(lib, lib.layout.cell_by_name("StaticBox"))
lib_proxy = ly.cell(lib_proxy_id)
assert_equal(lib_proxy.display_title, "PCellTestLib.StaticBox")
assert_equal(lib_proxy.basic_name, "StaticBox")
assert_equal(lib_proxy.layout.inspect, ly.inspect)
assert_equal(lib_proxy.library.inspect, lib.inspect)
assert_equal(lib_proxy.is_pcell_variant?, false)
assert_equal(lib.layout.cell(lib.layout.cell_by_name("StaticBox")).library.inspect, "nil")
lib_proxy_id = ly.add_lib_cell(lib, lib.layout.cell_by_name("StaticBox"))
lib_proxy = ly.cell(lib_proxy_id)
assert_equal(lib_proxy.display_title, "PCellTestLib.StaticBox")
assert_equal(lib_proxy.basic_name, "StaticBox")
assert_equal(lib_proxy.layout.inspect, ly.inspect)
assert_equal(lib_proxy.library.inspect, lib.inspect)
assert_equal(lib_proxy.is_pcell_variant?, false)
assert_equal(lib.layout.cell(lib.layout.cell_by_name("StaticBox")).library.inspect, "nil")
li2 = ly.layer_indices.find { |li| ly.get_info(li).to_s == "10/0" }
assert_equal(li2 != nil, true)
li2 = ly.layer_indices.find { |li| ly.get_info(li).to_s == "10/0" }
assert_equal(li2 != nil, true)
assert_equal(ly.begin_shapes(c1.cell_index, li1).shape.to_s, "box (-250,-500;250,500)")
assert_equal(ly.begin_shapes(lib_proxy.cell_index, li2).shape.to_s, "box (0,0;10,20)")
assert_equal(ly.begin_shapes(c1.cell_index, li1).shape.to_s, "box (-250,-500;250,500)")
assert_equal(ly.begin_shapes(lib_proxy.cell_index, li2).shape.to_s, "box (0,0;10,20)")
param = { "w" => 1, "h" => 2 }
c1.change_pcell_parameters(pcell_inst, param)
assert_equal(ly.begin_shapes(c1.cell_index, li1).shape.to_s, "box (-50,-100;50,100)")
param = [ RBA::LayerInfo::new(1, 0), 5.0, 5.0 ]
c1.change_pcell_parameters(pcell_inst, param)
assert_equal(ly.begin_shapes(c1.cell_index, li1).shape.to_s, "box (-250,-250;250,250)")
pcell_inst.change_pcell_parameters({ "w" => 2.0, "h" => 10.0 })
assert_equal(ly.begin_shapes(c1.cell_index, li1).shape.to_s, "box (-100,-500;100,500)")
param = { "w" => 1, "h" => 2 }
c1.change_pcell_parameters(pcell_inst, param)
assert_equal(ly.begin_shapes(c1.cell_index, li1).shape.to_s, "box (-50,-100;50,100)")
param = [ RBA::LayerInfo::new(1, 0), 5.0, 5.0 ]
c1.change_pcell_parameters(pcell_inst, param)
assert_equal(ly.begin_shapes(c1.cell_index, li1).shape.to_s, "box (-250,-250;250,250)")
pcell_inst.change_pcell_parameters({ "w" => 2.0, "h" => 10.0 })
assert_equal(ly.begin_shapes(c1.cell_index, li1).shape.to_s, "box (-100,-500;100,500)")
pcell_inst.change_pcell_parameters([ RBA::LayerInfo::new(1, 0), 5.0, 5.0 ])
assert_equal(ly.begin_shapes(c1.cell_index, li1).shape.to_s, "box (-250,-250;250,250)")
pcell_inst.change_pcell_parameters([ RBA::LayerInfo::new(1, 0), 5.0, 5.0 ])
assert_equal(ly.begin_shapes(c1.cell_index, li1).shape.to_s, "box (-250,-250;250,250)")
pcell_inst.change_pcell_parameter("w", 5.0)
pcell_inst.change_pcell_parameter("h", 1.0)
assert_equal(ly.begin_shapes(c1.cell_index, li1).shape.to_s, "box (-250,-50;250,50)")
pcell_inst.change_pcell_parameter("w", 5.0)
pcell_inst.change_pcell_parameter("h", 1.0)
assert_equal(ly.begin_shapes(c1.cell_index, li1).shape.to_s, "box (-250,-50;250,50)")
c1.change_pcell_parameter(pcell_inst, "w", 10.0)
c1.change_pcell_parameter(pcell_inst, "h", 2.0)
assert_equal(ly.begin_shapes(c1.cell_index, li1).shape.to_s, "box (-500,-100;500,100)")
c1.change_pcell_parameter(pcell_inst, "w", 10.0)
c1.change_pcell_parameter(pcell_inst, "h", 2.0)
assert_equal(ly.begin_shapes(c1.cell_index, li1).shape.to_s, "box (-500,-100;500,100)")
assert_equal(ly.cell(pcell_inst.cell_index).is_pcell_variant?, true)
assert_equal(pcell_inst.is_pcell?, true)
new_id = ly.convert_cell_to_static(pcell_inst.cell_index)
assert_equal(new_id == pcell_inst.cell_index, false)
assert_equal(ly.cell(new_id).is_pcell_variant?, false)
param = [ RBA::LayerInfo::new(1, 0), 5.0, 5.0 ]
c1.change_pcell_parameters(pcell_inst, param)
assert_equal(ly.begin_shapes(c1.cell_index, li1).shape.to_s, "box (-250,-250;250,250)")
pcell_inst.cell_index = new_id
assert_equal(ly.begin_shapes(c1.cell_index, li1).shape.to_s, "box (-500,-100;500,100)")
assert_equal(ly.cell(pcell_inst.cell_index).is_pcell_variant?, true)
assert_equal(pcell_inst.is_pcell?, true)
new_id = ly.convert_cell_to_static(pcell_inst.cell_index)
assert_equal(new_id == pcell_inst.cell_index, false)
assert_equal(ly.cell(new_id).is_pcell_variant?, false)
param = [ RBA::LayerInfo::new(1, 0), 5.0, 5.0 ]
c1.change_pcell_parameters(pcell_inst, param)
assert_equal(ly.begin_shapes(c1.cell_index, li1).shape.to_s, "box (-250,-250;250,250)")
pcell_inst.cell_index = new_id
assert_equal(ly.begin_shapes(c1.cell_index, li1).shape.to_s, "box (-500,-100;500,100)")
l10 = ly.layer(10, 0)
c1.shapes(l10).insert(RBA::Box::new(0, 10, 100, 210))
l11 = ly.layer(11, 0)
c1.shapes(l11).insert(RBA::Text::new("hello", RBA::Trans::new))
assert_equal(pcell_decl.can_create_from_shape(ly, ly.begin_shapes(c1.cell_index(), l11).shape(), l10), false)
assert_equal(pcell_decl.can_create_from_shape(ly, ly.begin_shapes(c1.cell_index(), l10).shape(), l10), true)
assert_equal(pcell_decl.parameters_from_shape(ly, ly.begin_shapes(c1.cell_index(), l10).shape(), l10).inspect, "[<10/0>, 1.0, 2.0]")
assert_equal(pcell_decl.transformation_from_shape(ly, ly.begin_shapes(c1.cell_index(), l10).shape(), l10).to_s, "r0 50,110")
l10 = ly.layer(10, 0)
c1.shapes(l10).insert(RBA::Box::new(0, 10, 100, 210))
l11 = ly.layer(11, 0)
c1.shapes(l11).insert(RBA::Text::new("hello", RBA::Trans::new))
assert_equal(pcell_decl.can_create_from_shape(ly, ly.begin_shapes(c1.cell_index(), l11).shape(), l10), false)
assert_equal(pcell_decl.can_create_from_shape(ly, ly.begin_shapes(c1.cell_index(), l10).shape(), l10), true)
assert_equal(pcell_decl.parameters_from_shape(ly, ly.begin_shapes(c1.cell_index(), l10).shape(), l10).inspect, "[<10/0>, 1.0, 2.0]")
assert_equal(pcell_decl.transformation_from_shape(ly, ly.begin_shapes(c1.cell_index(), l10).shape(), l10).to_s, "r0 50,110")
ly.destroy
ensure
tl.delete
end
ly._destroy
tl._destroy
end
@ -348,63 +348,84 @@ class DBPCell_TestClass < TestBase
# instantiate and register the library
tl = PCellTestLib2::new
begin
ly = RBA::Layout::new(true)
ly.dbu = 0.01
ly = RBA::Layout::new(true)
ly.dbu = 0.01
ci1 = ly.add_cell("c1")
c1 = ly.cell(ci1)
ci1 = ly.add_cell("c1")
c1 = ly.cell(ci1)
lib = RBA::Library.library_by_name("PCellTestLib2")
assert_equal(lib != nil, true)
pcell_decl = lib.layout().pcell_declaration("Box2")
lib = RBA::Library.library_by_name("PCellTestLib2")
assert_equal(lib != nil, true)
pcell_decl = lib.layout().pcell_declaration("Box2")
param = [ RBA::LayerInfo::new(1, 0) ] # rest is filled with defaults
pcell_var_id = ly.add_pcell_variant(lib, pcell_decl.id(), param)
pcell_var = ly.cell(pcell_var_id)
pcell_inst = c1.insert(RBA::CellInstArray::new(pcell_var_id, RBA::Trans::new))
assert_equal(pcell_var.basic_name, "Box2")
assert_equal(pcell_var.pcell_parameters().inspect, "[<1/0>, 1.0, 1.0, 0]")
assert_equal(pcell_var.display_title(), "PCellTestLib2.Box2(L=1/0,W=1.000,H=1.000)")
assert_equal(norm_hash(pcell_var.pcell_parameters_by_name()), "{\"height\"=>1.0, \"layer\"=><1/0>, \"secret\"=>0, \"width\"=>1.0}")
assert_equal(pcell_var.pcell_parameter("height").inspect(), "1.0")
assert_equal(c1.pcell_parameters(pcell_inst).inspect(), "[<1/0>, 1.0, 1.0, 0]")
assert_equal(c1.pcell_parameter(pcell_inst, "secret"), 0)
assert_equal(norm_hash(c1.pcell_parameters_by_name(pcell_inst)), "{\"height\"=>1.0, \"layer\"=><1/0>, \"secret\"=>0, \"width\"=>1.0}")
assert_equal(c1.pcell_parameter(pcell_inst, "height").inspect(), "1.0")
assert_equal(norm_hash(pcell_inst.pcell_parameters_by_name()), "{\"height\"=>1.0, \"layer\"=><1/0>, \"secret\"=>0, \"width\"=>1.0}")
assert_equal(pcell_inst["height"].inspect(), "1.0")
assert_equal(pcell_inst.pcell_parameter("height").inspect(), "1.0")
assert_equal(pcell_var.pcell_declaration().inspect(), pcell_decl.inspect)
assert_equal(c1.pcell_declaration(pcell_inst).inspect(), pcell_decl.inspect)
assert_equal(pcell_inst.pcell_declaration().inspect(), pcell_decl.inspect)
param = [ RBA::LayerInfo::new(1, 0) ] # rest is filled with defaults
pcell_var_id = ly.add_pcell_variant(lib, pcell_decl.id(), param)
pcell_var = ly.cell(pcell_var_id)
pcell_inst = c1.insert(RBA::CellInstArray::new(pcell_var_id, RBA::Trans::new))
assert_equal(pcell_var.basic_name, "Box2")
assert_equal(pcell_var.pcell_parameters().inspect, "[<1/0>, 1.0, 1.0]")
assert_equal(pcell_var.display_title(), "PCellTestLib2.Box2(L=1/0,W=1.000,H=1.000)")
assert_equal(norm_hash(pcell_var.pcell_parameters_by_name()), "{\"height\"=>1.0, \"layer\"=><1/0>, \"width\"=>1.0}")
assert_equal(pcell_var.pcell_parameter("height").inspect(), "1.0")
assert_equal(c1.pcell_parameters(pcell_inst).inspect(), "[<1/0>, 1.0, 1.0]")
assert_equal(norm_hash(c1.pcell_parameters_by_name(pcell_inst)), "{\"height\"=>1.0, \"layer\"=><1/0>, \"width\"=>1.0}")
assert_equal(c1.pcell_parameter(pcell_inst, "height").inspect(), "1.0")
assert_equal(norm_hash(pcell_inst.pcell_parameters_by_name()), "{\"height\"=>1.0, \"layer\"=><1/0>, \"width\"=>1.0}")
assert_equal(pcell_inst["height"].inspect(), "1.0")
assert_equal(pcell_inst.pcell_parameter("height").inspect(), "1.0")
assert_equal(pcell_var.pcell_declaration().inspect(), pcell_decl.inspect)
assert_equal(c1.pcell_declaration(pcell_inst).inspect(), pcell_decl.inspect)
assert_equal(pcell_inst.pcell_declaration().inspect(), pcell_decl.inspect)
li1 = ly.layer(1, 0)
assert_equal(li1 == nil, false)
pcell_inst.change_pcell_parameter("height", 2.0)
assert_equal(norm_hash(pcell_inst.pcell_parameters_by_name()), "{\"height\"=>2.0, \"layer\"=><1/0>, \"secret\"=>0, \"width\"=>1.0}")
li1 = ly.layer(1, 0)
assert_equal(li1 == nil, false)
pcell_inst.change_pcell_parameter("height", 2.0)
assert_equal(norm_hash(pcell_inst.pcell_parameters_by_name()), "{\"height\"=>2.0, \"layer\"=><1/0>, \"width\"=>1.0}")
assert_equal(ly.begin_shapes(c1.cell_index(), li1).shape().to_s, "box (-50,-100;50,100)")
assert_equal(ly.begin_shapes(c1.cell_index(), li1).shape().to_s, "box (-50,-100;50,100)")
param = { "layer" => RBA::LayerInfo::new(2, 0), "width" => 2, "height" => 1 }
li2 = ly.layer(2, 0)
c1.change_pcell_parameters(pcell_inst, param)
assert_equal(ly.begin_shapes(c1.cell_index(), li2).shape().to_s, "box (-100,-50;100,50)")
param = { "layer" => RBA::LayerInfo::new(2, 0), "width" => 2, "height" => 1 }
li2 = ly.layer(2, 0)
c1.change_pcell_parameters(pcell_inst, param)
assert_equal(ly.begin_shapes(c1.cell_index(), li2).shape().to_s, "box (-100,-50;100,50)")
l10 = ly.layer(10, 0)
c1.shapes(l10).insert(RBA::Box::new(0, 10, 100, 210))
l11 = ly.layer(11, 0)
c1.shapes(l11).insert(RBA::Text::new("hello", RBA::Trans::new))
assert_equal(pcell_decl.can_create_from_shape(ly, ly.begin_shapes(c1.cell_index(), l11).shape(), l10), false)
assert_equal(pcell_decl.can_create_from_shape(ly, ly.begin_shapes(c1.cell_index(), l10).shape(), l10), true)
assert_equal(pcell_decl.parameters_from_shape(ly, ly.begin_shapes(c1.cell_index(), l10).shape(), l10).inspect, "[<10/0>, 1.0, 2.0, 0]")
assert_equal(pcell_decl.transformation_from_shape(ly, ly.begin_shapes(c1.cell_index(), l10).shape(), l10).to_s, "r0 50,110")
l10 = ly.layer(10, 0)
c1.shapes(l10).insert(RBA::Box::new(0, 10, 100, 210))
l11 = ly.layer(11, 0)
c1.shapes(l11).insert(RBA::Text::new("hello", RBA::Trans::new))
assert_equal(pcell_decl.can_create_from_shape(ly, ly.begin_shapes(c1.cell_index(), l11).shape(), l10), false)
assert_equal(pcell_decl.can_create_from_shape(ly, ly.begin_shapes(c1.cell_index(), l10).shape(), l10), true)
assert_equal(pcell_decl.parameters_from_shape(ly, ly.begin_shapes(c1.cell_index(), l10).shape(), l10).inspect, "[<10/0>, 1.0, 2.0]")
assert_equal(pcell_decl.transformation_from_shape(ly, ly.begin_shapes(c1.cell_index(), l10).shape(), l10).to_s, "r0 50,110")
param2 = c1.pcell_parameters(pcell_inst)
param2[3] = -2 # "secret"
pcell_var_id2 = ly.add_pcell_variant(lib, pcell_decl.id(), param2)
pcell_var2 = ly.cell(pcell_var_id2)
pcell_inst2 = c1.insert(RBA::CellInstArray::new(pcell_var_id2, RBA::Trans::new))
ly.destroy
assert_equal(c1.pcell_parameter(pcell_inst2, "secret"), -2) # coerce_parameters NOT called!
assert_not_equal(pcell_inst.cell.library_cell_index, pcell_inst2.cell.library_cell_index)
ensure
tl.delete
end
param = { "secret" => -1 }
c1.change_pcell_parameters(pcell_inst, param)
assert_equal(c1.pcell_parameter(pcell_inst, "secret"), -1) # coerce_parameters NOT called!
tl.refresh
assert_equal(c1.pcell_parameter(pcell_inst2, "secret"), 0) # coerce_parameters was called
assert_equal(c1.pcell_parameter(pcell_inst, "secret"), 0) # coerce_parameters was called
# same variant now
assert_equal(pcell_inst.cell.library_cell_index, pcell_inst2.cell.library_cell_index)
param = { "secret" => 42 }
c1.change_pcell_parameters(pcell_inst, param)
assert_equal(c1.pcell_parameter(pcell_inst, "secret"), 42)
assert_not_equal(pcell_inst.cell.library_cell_index, pcell_inst2.cell.library_cell_index)
ly._destroy
tl._destroy
end
@ -413,43 +434,38 @@ class DBPCell_TestClass < TestBase
# instantiate and register the library
tl = PCellTestLib::new
begin
ly = RBA::Layout::new(true)
ly.dbu = 0.01
ly = RBA::Layout::new(true)
ly.dbu = 0.01
ci1 = ly.add_cell("c1")
c1 = ly.cell(ci1)
ci1 = ly.add_cell("c1")
c1 = ly.cell(ci1)
lib = RBA::Library::library_by_name("PCellTestLib")
pcell_decl_id = lib.layout.pcell_id("Box")
lib = RBA::Library::library_by_name("PCellTestLib")
pcell_decl_id = lib.layout.pcell_id("Box")
param = [ RBA::LayerInfo::new(1, 0), 10.0, 2.0 ]
pcell_var_id = ly.add_pcell_variant(lib, pcell_decl_id, param)
pcell_var = ly.cell(pcell_var_id)
pcell_inst = c1.insert(RBA::CellInstArray::new(pcell_var_id, RBA::Trans::new))
param = [ RBA::LayerInfo::new(1, 0), 10.0, 2.0 ]
pcell_var_id = ly.add_pcell_variant(lib, pcell_decl_id, param)
pcell_var = ly.cell(pcell_var_id)
pcell_inst = c1.insert(RBA::CellInstArray::new(pcell_var_id, RBA::Trans::new))
li1 = ly.layer_indices.find { |li| ly.get_info(li).to_s == "1/0" }
assert_equal(li1 != nil, true)
assert_equal(ly.is_valid_layer?(li1), true)
assert_equal(ly.get_info(li1).to_s, "1/0")
li1 = ly.layer_indices.find { |li| ly.get_info(li).to_s == "1/0" }
assert_equal(li1 != nil, true)
assert_equal(ly.is_valid_layer?(li1), true)
assert_equal(ly.get_info(li1).to_s, "1/0")
assert_equal(pcell_inst.is_pcell?, true)
assert_equal(pcell_inst.is_pcell?, true)
assert_equal(ly.begin_shapes(pcell_inst.cell_index, li1).shape.to_s, "box (-500,-100;500,100)")
pcell_inst.convert_to_static
assert_equal(pcell_inst.is_pcell?, false)
assert_equal(ly.begin_shapes(pcell_inst.cell_index, li1).shape.to_s, "box (-500,-100;500,100)")
pcell_inst.convert_to_static
assert_equal(pcell_inst.is_pcell?, false)
assert_equal(ly.begin_shapes(pcell_inst.cell_index, li1).shape.to_s, "box (-500,-100;500,100)")
assert_equal(ly.begin_shapes(pcell_inst.cell_index, li1).shape.to_s, "box (-500,-100;500,100)")
pcell_inst.convert_to_static
assert_equal(pcell_inst.is_pcell?, false)
assert_equal(ly.begin_shapes(pcell_inst.cell_index, li1).shape.to_s, "box (-500,-100;500,100)")
pcell_inst.convert_to_static
assert_equal(pcell_inst.is_pcell?, false)
assert_equal(ly.begin_shapes(pcell_inst.cell_index, li1).shape.to_s, "box (-500,-100;500,100)")
ly._destroy
tl._destroy
#ly.destroy
ensure
#tl.delete
end
end
def test_3
@ -457,27 +473,24 @@ class DBPCell_TestClass < TestBase
# instantiate and register the library
tl = PCellTestLib::new
begin
ly = RBA::Layout::new(true)
ly.dbu = 0.01
ly = RBA::Layout::new(true)
ly.dbu = 0.01
c1 = ly.create_cell("c1")
c1 = ly.create_cell("c1")
lib = RBA::Library::library_by_name("PCellTestLib")
pcell_decl_id = lib.layout.pcell_id("Box")
lib = RBA::Library::library_by_name("PCellTestLib")
pcell_decl_id = lib.layout.pcell_id("Box")
param = { "w" => 4.0, "h" => 8.0, "l" => RBA::LayerInfo::new(1, 0) }
pcell_var_id = ly.add_pcell_variant(lib, pcell_decl_id, param)
pcell_var = ly.cell(pcell_var_id)
pcell_inst = c1.insert(RBA::CellInstArray::new(pcell_var_id, RBA::Trans::new))
param = { "w" => 4.0, "h" => 8.0, "l" => RBA::LayerInfo::new(1, 0) }
pcell_var_id = ly.add_pcell_variant(lib, pcell_decl_id, param)
pcell_var = ly.cell(pcell_var_id)
pcell_inst = c1.insert(RBA::CellInstArray::new(pcell_var_id, RBA::Trans::new))
assert_equal(ly.begin_shapes(c1.cell_index, ly.layer(1, 0)).shape.to_s, "box (-200,-400;200,400)")
ensure
#tl.delete
end
assert_equal(ly.begin_shapes(c1.cell_index, ly.layer(1, 0)).shape.to_s, "box (-200,-400;200,400)")
ly._destroy
tl._destroy
end
def test_4
@ -485,20 +498,16 @@ class DBPCell_TestClass < TestBase
# instantiate and register the library
tl = PCellTestLib::new
begin
lib = RBA::Library::library_by_name("PCellTestLib")
pcell_decl_id = lib.layout.pcell_id("Box")
lib = RBA::Library::library_by_name("PCellTestLib")
pcell_decl_id = lib.layout.pcell_id("Box")
param = { "w" => 4.0, "h" => 8.0, "l" => RBA::LayerInfo::new(1, 0) }
pcell_var_id = lib.layout.add_pcell_variant(pcell_decl_id, param)
param = { "w" => 4.0, "h" => 8.0, "l" => RBA::LayerInfo::new(1, 0) }
pcell_var_id = lib.layout.add_pcell_variant(pcell_decl_id, param)
assert_equal(lib.layout.begin_shapes(pcell_var_id, lib.layout.layer(1, 0)).shape.to_s, "box (-2000,-4000;2000,4000)")
ensure
#tl.delete
end
assert_equal(lib.layout.begin_shapes(pcell_var_id, lib.layout.layer(1, 0)).shape.to_s, "box (-2000,-4000;2000,4000)")
tl._destroy
end
def test_5
@ -506,19 +515,15 @@ class DBPCell_TestClass < TestBase
# instantiate and register the library
tl = PCellTestLib::new
begin
lib = RBA::Library::library_by_name("PCellTestLib")
pcell_decl_id = lib.layout.pcell_id("Box")
lib = RBA::Library::library_by_name("PCellTestLib")
pcell_decl_id = lib.layout.pcell_id("Box")
param = { "w" => 3.0, "h" => 7.0, "l" => RBA::LayerInfo::new(2, 0) }
pcell_var_id = lib.layout.add_pcell_variant(pcell_decl_id, param)
param = { "w" => 3.0, "h" => 7.0, "l" => RBA::LayerInfo::new(2, 0) }
pcell_var_id = lib.layout.add_pcell_variant(pcell_decl_id, param)
assert_equal(lib.layout.begin_shapes(pcell_var_id, lib.layout.layer(2, 0)).shape.to_s, "box (-1500,-3500;1500,3500)")
assert_equal(lib.layout.begin_shapes(pcell_var_id, lib.layout.layer(2, 0)).shape.to_s, "box (-1500,-3500;1500,3500)")
ensure
#tl.delete
end
tl._destroy
end
@ -527,18 +532,14 @@ class DBPCell_TestClass < TestBase
# instantiate and register the library
tl = PCellTestLib::new
begin
lib = RBA::Library::library_by_name("PCellTestLib")
lib = RBA::Library::library_by_name("PCellTestLib")
param = { "w" => 3.0, "h" => 8.0, "l" => RBA::LayerInfo::new(3, 0) }
pcell_var = lib.layout.create_cell("Box", param)
param = { "w" => 3.0, "h" => 8.0, "l" => RBA::LayerInfo::new(3, 0) }
pcell_var = lib.layout.create_cell("Box", param)
assert_equal(lib.layout.begin_shapes(pcell_var.cell_index, lib.layout.layer(3, 0)).shape.to_s, "box (-1500,-4000;1500,4000)")
assert_equal(lib.layout.begin_shapes(pcell_var.cell_index, lib.layout.layer(3, 0)).shape.to_s, "box (-1500,-4000;1500,4000)")
ensure
#tl.delete
end
tl._destroy
end
@ -547,19 +548,16 @@ class DBPCell_TestClass < TestBase
# instantiate and register the library
tl = PCellTestLib::new
begin
ly = RBA::Layout::new(true)
ly.dbu = 0.01
ly = RBA::Layout::new(true)
ly.dbu = 0.01
param = { "w" => 4.0, "h" => 8.0, "l" => RBA::LayerInfo::new(4, 0) }
cell = ly.create_cell("Box", "PCellTestLib", param)
param = { "w" => 4.0, "h" => 8.0, "l" => RBA::LayerInfo::new(4, 0) }
cell = ly.create_cell("Box", "PCellTestLib", param)
assert_equal(ly.begin_shapes(cell, ly.layer(4, 0)).shape.to_s, "box (-200,-400;200,400)")
assert_equal(ly.begin_shapes(cell, ly.layer(4, 0)).shape.to_s, "box (-200,-400;200,400)")
ensure
#tl.delete
end
tl._destroy
ly._destroy
end
@ -568,23 +566,20 @@ class DBPCell_TestClass < TestBase
# instantiate and register the library
tl = PCellTestLib::new
begin
lib = RBA::Library::library_by_name("PCellTestLib")
ly = RBA::Layout::new(true)
ly.dbu = 0.01
lib = RBA::Library::library_by_name("PCellTestLib")
ly = RBA::Layout::new(true)
ly.dbu = 0.01
param = { "w" => 2.0, "h" => 6.0, "l" => RBA::LayerInfo::new(5, 0) }
pcell_var = lib.layout.create_cell("Box", param)
pcell_var.name = "BOXVAR"
param = { "w" => 2.0, "h" => 6.0, "l" => RBA::LayerInfo::new(5, 0) }
pcell_var = lib.layout.create_cell("Box", param)
pcell_var.name = "BOXVAR"
cell = ly.create_cell("BOXVAR", "PCellTestLib")
cell = ly.create_cell("BOXVAR", "PCellTestLib")
assert_equal(cell.begin_shapes_rec(ly.layer(5, 0)).shape.to_s, "box (-100,-300;100,300)")
assert_equal(cell.begin_shapes_rec(ly.layer(5, 0)).shape.to_s, "box (-100,-300;100,300)")
ensure
#tl.delete
end
tl._destroy
ly._destroy
end
@ -601,6 +596,8 @@ class DBPCell_TestClass < TestBase
assert_equal(pcell.layout == nil, false)
assert_equal(pcell.layout.object_id == layout.object_id, true)
layout._destroy
end
end