netlist: Further simplification and optimization. (nw)

This commit is contained in:
couriersud 2019-02-04 19:22:21 +01:00
parent fa72f0bfe3
commit 759b7c3c88
12 changed files with 300 additions and 190 deletions

View File

@ -1,3 +1,4 @@
// license:GPL-2.0+
// copyright-holders:Couriersud
/*
@ -110,6 +111,7 @@ namespace netlist
NETLIB_RESET(7474)
{
m_CLK.set_state(logic_t::STATE_INP_LH);
m_D.set_state(logic_t::STATE_INP_ACTIVE);
m_nextD = 0;
}

View File

@ -86,7 +86,6 @@ namespace devices
static constexpr const std::size_t m_num_bits = m_NI;
static constexpr const std::size_t m_size = (1 << (m_num_bits));
static constexpr const type_t m_outmask = ((1 << m_NO) - 1);
static constexpr const std::size_t m_min_inputs_for_deactivate = 2;
struct truthtable_t
{
@ -106,7 +105,6 @@ namespace devices
: device_t(owner, name)
, m_fam(*this, fam)
, m_ign(*this, "m_ign", 0)
, m_active_outputs(*this, "m_active_outputs", 1)
, m_ttp(ttp)
{
init(desc);
@ -116,13 +114,14 @@ namespace devices
NETLIB_RESETI()
{
m_active_outputs = 0;
int active_outputs = 0;
m_ign = 0;
for (auto &i : m_I)
i.activate();
for (auto &q : m_Q)
if (q.has_net() && q.net().num_cons() > 0)
m_active_outputs++;
active_outputs++;
set_active_outputs(active_outputs);
}
NETLIB_UPDATEI()
@ -132,28 +131,14 @@ namespace devices
void inc_active() NL_NOEXCEPT override
{
if (m_NI >= m_min_inputs_for_deactivate)
if (++m_active_outputs == 1)
{
process<false>();
}
process<false>();
}
void dec_active() NL_NOEXCEPT override
{
/* FIXME:
* Based on current measurements there is no point to disable
* 1 input devices. This should actually be a parameter so that we
* can decide for each individual gate whether it is beneficial to
* ignore deactivation.
*/
if (m_NI >= m_min_inputs_for_deactivate)
if (--m_active_outputs == 0)
{
for (std::size_t i = 0; i< m_NI; i++)
m_I[i].inactivate();
m_ign = (1<<m_NI)-1;
}
for (std::size_t i = 0; i< m_NI; i++)
m_I[i].inactivate();
m_ign = (1<<m_NI)-1;
}
plib::uninitialised_array_t<logic_input_t, m_NI> m_I;
@ -169,52 +154,35 @@ namespace devices
netlist_time mt(netlist_time::zero());
type_t nstate(0);
if (m_NI >= m_min_inputs_for_deactivate)
{
type_t ign(m_ign);
type_t ign(m_ign);
#if 1
if (!doOUT)
for (std::size_t i = 0; i < m_NI; i++)
{
m_I[i].activate();
//nstate |= (m_I[i]() ? (1 << i) : 0);
nstate |= (m_I[i]() << i);
mt = std::max(this->m_I[i].net().next_scheduled_time(), mt);
}
else
for (std::size_t i = 0; i < m_NI; i++)
{
if ((ign & 1))
m_I[i].activate();
//nstate |= (m_I[i]() ? (1 << i) : 0);
nstate |= (m_I[i]() << i);
ign >>= 1;
}
#else
if (!doOUT)
if (!doOUT)
for (std::size_t i = 0; i < m_NI; i++)
{
nstate = aa<m_NI, type_t>().f(m_I, ~0);
for (std::size_t i = 0; i < m_NI; i++)
mt = std::max(this->m_I[i].net().time(), mt);
m_I[i].activate();
//nstate |= (m_I[i]() ? (1 << i) : 0);
nstate |= (m_I[i]() << i);
mt = std::max(this->m_I[i].net().next_scheduled_time(), mt);
}
else
nstate = aa<m_NI, type_t>().f(m_I, ign);
#endif
else
for (std::size_t i = 0; i < m_NI; i++)
{
if ((ign & 1))
m_I[i].activate();
//nstate |= (m_I[i]() ? (1 << i) : 0);
nstate |= (m_I[i]() << i);
ign >>= 1;
}
#else
if (!doOUT)
{
nstate = aa<m_NI, type_t>().f(m_I, ~0);
for (std::size_t i = 0; i < m_NI; i++)
mt = std::max(this->m_I[i].net().time(), mt);
}
else
{
if (!doOUT)
for (std::size_t i = 0; i < m_NI; i++)
{
//nstate |= (m_I[i]() ? (1 << i) : 0);
nstate |= (m_I[i]() << i);
mt = std::max(this->m_I[i].net().next_scheduled_time(), mt);
}
else
for (std::size_t i = 0; i < m_NI; i++)
//nstate |= (m_I[i]() ? (1 << i) : 0);
nstate |= (m_I[i]() << i);
}
nstate = aa<m_NI, type_t>().f(m_I, ign);
#endif
const type_t outstate(m_ttp.m_out_state[nstate]);
type_t out(outstate & m_outmask);
@ -232,18 +200,14 @@ namespace devices
for (std::size_t i = 0; i < m_NO; out >>= 1, ++i)
m_Q[i].set_Q_time(out & 1, mt + tim[t[i]]);
if (m_NI >= m_min_inputs_for_deactivate)
{
type_t ign(m_ign);
for (auto I = m_I.begin(); ign != 0; ign >>= 1, ++I)
if (ign & 1)
I->inactivate();
}
ign = m_ign;
for (auto I = m_I.begin(); ign != 0; ign >>= 1, ++I)
if (ign & 1)
I->inactivate();
}
/* FIXME: check width */
state_var<type_t> m_ign;
state_var_s32 m_active_outputs;
const truthtable_t &m_ttp;
};

View File

@ -430,7 +430,7 @@ void netlist_t::process_queue(const netlist_time delta) NL_NOEXCEPT
m_queue.push(detail::queue_t::entry_t(stop, nullptr));
m_stat_mainloop.start();
auto sm_guard(m_stat_mainloop.guard());
if (m_mainclock == nullptr)
{
@ -472,7 +472,6 @@ void netlist_t::process_queue(const netlist_time delta) NL_NOEXCEPT
} while (true); //while (e.m_object != nullptr);
mc_net.set_next_scheduled_time(mc_time);
}
m_stat_mainloop.stop();
}
void netlist_t::print_stats() const
@ -504,13 +503,13 @@ void netlist_t::print_stats() const
nperftime_t<NL_KEEP_STATISTICS> overhead;
nperftime_t<NL_KEEP_STATISTICS> test;
overhead.start();
for (int j=0; j<100000;j++)
{
test.start();
test.stop();
auto overhead_guard(overhead.guard());
for (int j=0; j<100000;j++)
{
auto test_guard(test.guard());
}
}
overhead.stop();
nperftime_t<NL_KEEP_STATISTICS>::type total_overhead = overhead()
* static_cast<nperftime_t<NL_KEEP_STATISTICS>::type>(total_count)
@ -518,6 +517,8 @@ void netlist_t::print_stats() const
log().verbose("Queue Pushes {1:15}", m_queue.m_prof_call());
log().verbose("Queue Moves {1:15}", m_queue.m_prof_sortmove());
log().verbose("Queue Removes {1:15}", m_queue.m_prof_remove());
log().verbose("Queue Retimes {1:15}", m_queue.m_prof_retime());
log().verbose("Total loop {1:15}", m_stat_mainloop());
/* Only one serialization should be counted in total time */
@ -570,6 +571,7 @@ core_device_t::core_device_t(netlist_base_t &owner, const pstring &name)
, logic_family_t()
, netlist_ref(owner)
, m_hint_deactivate(false)
, m_active_outputs(*this, "m_active_outputs", 1)
{
if (logic_family() == nullptr)
set_logic_family(family_TTL());
@ -580,6 +582,7 @@ core_device_t::core_device_t(core_device_t &owner, const pstring &name)
, logic_family_t()
, netlist_ref(owner.state())
, m_hint_deactivate(false)
, m_active_outputs(*this, "m_active_outputs", 1)
{
set_logic_family(owner.logic_family());
if (logic_family() == nullptr)
@ -723,9 +726,10 @@ void detail::net_t::process(const T mask)
p.device().m_stat_call_count.inc();
if ((p.terminal_state() & mask))
{
p.device().m_stat_total_time.start();
auto g(p.device().m_stat_total_time.guard());
//p.device().m_stat_total_time.start();
p.m_delegate();
p.device().m_stat_total_time.stop();
//p.device().m_stat_total_time.stop();
}
}
}
@ -740,16 +744,16 @@ void detail::net_t::update_devs() NL_NOEXCEPT
| (m_cur_Q << core_terminal_t::INP_HL_SHIFT));
m_in_queue = QS_DELIVERED; /* mark as taken ... */
if (mask == core_terminal_t::STATE_INP_HL)
switch (mask)
{
m_cur_Q = new_Q;
process(core_terminal_t::STATE_INP_HL | core_terminal_t::STATE_INP_ACTIVE);
}
else if (mask == core_terminal_t::STATE_INP_LH)
{
m_cur_Q = new_Q;
process(core_terminal_t::STATE_INP_LH | core_terminal_t::STATE_INP_ACTIVE);
case core_terminal_t::STATE_INP_HL:
case core_terminal_t::STATE_INP_LH:
m_cur_Q = new_Q;
process(mask | core_terminal_t::STATE_INP_ACTIVE);
break;
default:
/* do nothing */
break;
}
}

View File

@ -493,9 +493,9 @@ namespace netlist
using list_t = std::vector<core_terminal_t *>;
static constexpr const unsigned INP_HL_SHIFT = 0;
static constexpr const unsigned INP_LH_SHIFT = 1;
static constexpr const unsigned INP_ACTIVE_SHIFT = 2;
static constexpr const auto INP_HL_SHIFT = 0;
static constexpr const auto INP_LH_SHIFT = 1;
static constexpr const auto INP_ACTIVE_SHIFT = 2;
enum state_e {
STATE_INP_PASSIVE = 0,
@ -1084,19 +1084,27 @@ namespace netlist
{
if (m_hint_deactivate)
{
m_stat_inc_active.inc();
inc_active();
if (++m_active_outputs == 1)
{
m_stat_inc_active.inc();
inc_active();
}
}
}
void do_dec_active() NL_NOEXCEPT
{
if (m_hint_deactivate)
dec_active();
if (--m_active_outputs == 0)
{
dec_active();
}
}
void set_hint_deactivate(bool v) { m_hint_deactivate = v; }
bool get_hint_deactivate() { return m_hint_deactivate; }
/* Has to be set in device reset */
void set_active_outputs(int n) { m_active_outputs = n; }
void set_default_delegate(detail::core_terminal_t &term);
@ -1124,7 +1132,8 @@ namespace netlist
virtual bool is_timestep() const { return false; }
private:
bool m_hint_deactivate;
bool m_hint_deactivate;
state_var_s32 m_active_outputs;
};
// -----------------------------------------------------------------------------

View File

@ -67,27 +67,27 @@ namespace netlist
struct QueueOp
{
static constexpr bool less(const pqentry_t &lhs, const pqentry_t &rhs) noexcept
inline static constexpr bool less(const pqentry_t &lhs, const pqentry_t &rhs) noexcept
{
return (lhs.m_exec_time < rhs.m_exec_time);
}
static constexpr bool lessequal(const pqentry_t &lhs, const pqentry_t &rhs) noexcept
inline static constexpr bool lessequal(const pqentry_t &lhs, const pqentry_t &rhs) noexcept
{
return (lhs.m_exec_time <= rhs.m_exec_time);
}
static constexpr bool equal(const pqentry_t &lhs, const pqentry_t &rhs) noexcept
inline static constexpr bool equal(const pqentry_t &lhs, const pqentry_t &rhs) noexcept
{
return lhs.m_object == rhs.m_object;
}
static constexpr bool equal(const pqentry_t &lhs, const Element &rhs) noexcept
inline static constexpr bool equal(const pqentry_t &lhs, const Element &rhs) noexcept
{
return lhs.m_object == rhs;
}
static constexpr pqentry_t never() noexcept { return pqentry_t(Time::never(), nullptr); }
inline static constexpr pqentry_t never() noexcept { return pqentry_t(Time::never(), nullptr); }
};
Time m_exec_time;
@ -109,29 +109,31 @@ namespace netlist
std::size_t capacity() const noexcept { return m_list.capacity() - 1; }
bool empty() const noexcept { return (m_end == &m_list[1]); }
void push(T &&e) noexcept
void push(T e) noexcept
{
/* Lock */
lock_guard_type lck(m_lock);
T * i(m_end);
for (; QueueOp::less(*(i - 1), e); --i)
T * i(m_end-1);
for (; QueueOp::less(*(i), e); --i)
{
*(i) = std::move(*(i-1));
*(i+1) = *(i);
m_prof_sortmove.inc();
}
*i = std::move(e);
*(i+1) = e;
++m_end;
m_prof_call.inc();
}
T pop() noexcept { return *(--m_end); }
const T top() const noexcept { return *(m_end-1); }
const T &top() const noexcept { return *(m_end-1); }
template <class R>
void remove(const R &elem) noexcept
void remove(const R elem) noexcept
{
/* Lock */
lock_guard_type lck(m_lock);
m_prof_remove.inc();
for (T * i = m_end - 1; i > &m_list[0]; --i)
{
if (QueueOp::equal(*i, elem))
@ -142,10 +144,12 @@ namespace netlist
}
}
void retime(const T &elem) noexcept
void retime(T elem) noexcept
{
/* Lock */
lock_guard_type lck(m_lock);
m_prof_retime.inc();
for (T * i = m_end - 1; i > &m_list[0]; --i)
{
if (QueueOp::equal(*i, elem)) // partial equal!
@ -195,6 +199,8 @@ namespace netlist
// profiling
nperfcount_t<KEEPSTAT> m_prof_sortmove;
nperfcount_t<KEEPSTAT> m_prof_call;
nperfcount_t<KEEPSTAT> m_prof_remove;
nperfcount_t<KEEPSTAT> m_prof_retime;
};
template <class T, bool TS, bool KEEPSTAT, class QueueOp = typename T::QueueOp>

View File

@ -172,6 +172,9 @@ namespace netlist
class source_t
{
public:
friend class setup_t;
enum type_t
{
SOURCE,
@ -187,10 +190,12 @@ namespace netlist
virtual ~source_t() { }
virtual bool parse(const pstring &name);
virtual std::unique_ptr<plib::pistream> stream(const pstring &name) = 0;
setup_t &setup() { return m_setup; }
type_t type() const { return m_type; }
protected:
virtual std::unique_ptr<plib::pistream> stream(const pstring &name) = 0;
private:
setup_t &m_setup;
const type_t m_type;
@ -370,6 +375,7 @@ namespace netlist
{
}
protected:
virtual std::unique_ptr<plib::pistream> stream(const pstring &name) override;
private:
@ -385,6 +391,7 @@ namespace netlist
{
}
protected:
virtual std::unique_ptr<plib::pistream> stream(const pstring &name) override;
private:
@ -399,6 +406,7 @@ namespace netlist
{
}
protected:
virtual std::unique_ptr<plib::pistream> stream(const pstring &name) override;
private:
@ -416,6 +424,8 @@ namespace netlist
}
virtual bool parse(const pstring &name) override;
protected:
virtual std::unique_ptr<plib::pistream> stream(const pstring &name) override;
private:

View File

@ -170,13 +170,22 @@ namespace chrono {
{
typedef typename T::type type;
typedef uint_least64_t ctype;
constexpr static bool enabled = enabled_;
struct guard_t
{
guard_t(timer &m) : m_m(m) { m_m.m_time -= T::start();; }
~guard_t() { m_m.m_time += T::stop(); ++m_m.m_count; }
private:
timer &m_m;
};
friend struct guard_t;
timer() : m_time(0), m_count(0) { }
type operator()() const { return m_time; }
void start() { m_time -= T::start(); }
void stop() { m_time += T::stop(); ++m_count; }
void reset() { m_time = 0; m_count = 0; }
type average() const { return (m_count == 0) ? 0 : m_time / m_count; }
type total() const { return m_time; }
@ -185,7 +194,7 @@ namespace chrono {
double as_seconds() const { return static_cast<double>(total())
/ static_cast<double>(T::per_second()); }
constexpr static bool enabled = enabled_;
guard_t guard() { return guard_t(*this); }
private:
type m_time;
ctype m_count;
@ -196,17 +205,24 @@ namespace chrono {
{
typedef typename T::type type;
typedef uint_least64_t ctype;
struct guard_t
{
guard_t() {}
~guard_t() {}
};
constexpr type operator()() const { return 0; }
void start() const { }
void stop() const { }
void reset() const { }
constexpr type average() const { return 0; }
constexpr type total() const { return 0; }
constexpr ctype count() const { return 0; }
constexpr double as_seconds() const { return 0.0; }
constexpr static bool enabled = false;
guard_t guard() { return guard_t(); }
};
} // namespace chrono
} // namespace plib

View File

@ -21,7 +21,7 @@
* if PHAS_RDTSCP == 1
*/
#ifndef PUSE_ACCURATE_STATS
#define PUSE_ACCURATE_STATS (1)
#define PUSE_ACCURATE_STATS (0)
#endif
/*

View File

@ -83,6 +83,7 @@ private:
// the list allows insertions / deletions if used properly
// ----------------------------------------------------------------------------------------
#if 0
template <class LC>
class linkedlist_t
{
@ -167,7 +168,103 @@ public:
private:
LC *m_head;
};
#else
template <class LC>
class linkedlist_t
{
public:
struct element_t
{
public:
friend class linkedlist_t<LC>;
constexpr element_t() : m_next(nullptr), m_prev(nullptr) {}
constexpr element_t(const element_t &rhs) = delete;
constexpr element_t(element_t &&rhs) = delete;
constexpr LC *next() const noexcept { return m_next; }
constexpr LC *prev() const noexcept { return m_prev; }
protected:
~element_t() = default;
private:
LC * m_next;
LC * m_prev;
};
struct iter_t final : public std::iterator<std::forward_iterator_tag, LC>
{
private:
LC* p;
public:
explicit constexpr iter_t(LC* x) noexcept : p(x) { }
explicit constexpr iter_t(iter_t &rhs) noexcept : p(rhs.p) { }
iter_t(iter_t &&rhs) noexcept { std::swap(*this, rhs); }
iter_t& operator=(iter_t &rhs) { iter_t t(rhs); std::swap(*this, t); return *this; }
iter_t& operator=(iter_t &&rhs) { std::swap(*this, rhs); return *this; }
iter_t& operator++() noexcept {p = p->next();return *this;}
iter_t operator++(int) noexcept {iter_t tmp(*this); operator++(); return tmp;}
constexpr bool operator==(const iter_t& rhs) const noexcept {return p == rhs.p;}
constexpr bool operator!=(const iter_t& rhs) const noexcept {return p != rhs.p;}
/* constexpr */ LC& operator*() noexcept {return *p;}
/* constexpr */ LC* operator->() noexcept {return p;}
constexpr LC& operator*() const noexcept {return *p;}
constexpr LC* operator->() const noexcept {return p;}
};
constexpr linkedlist_t() : m_head(nullptr) {}
constexpr iter_t begin() const noexcept { return iter_t(m_head); }
constexpr iter_t end() const noexcept { return iter_t(nullptr); }
void push_front(LC *elem) noexcept
{
elem->m_next = m_head;
elem->m_prev = nullptr;
if (elem->m_next)
elem->m_next->m_prev = elem;
m_head = elem;
}
void push_back(LC *elem) noexcept
{
LC ** p(&m_head);
LC * prev(nullptr);
while (*p != nullptr)
{
prev = *p;
p = &((*p)->m_next);
}
*p = elem;
elem->m_prev = prev;
elem->m_next = nullptr;
}
void remove(const LC *elem) noexcept
{
if (elem->m_prev)
elem->m_prev->m_next = elem->m_next;
else
m_head = elem->m_next;
if (elem->m_next)
elem->m_next->m_prev = elem->m_prev;
else
{
/* update tail */
}
}
LC *front() const noexcept { return m_head; }
void clear() noexcept { m_head = nullptr; }
constexpr bool empty() const noexcept { return (m_head == nullptr); }
private:
LC *m_head;
};
#endif
}
#endif /* PLISTS_H_ */

View File

@ -337,79 +337,83 @@ static std::vector<input_t> read_input(const netlist::setup_t &setup, pstring fn
void tool_app_t::run()
{
plib::chrono::timer<plib::chrono::system_ticks> t;
t.start();
std::vector<input_t> inps;
netlist::netlist_time ttr;
netlist_tool_t nt(*this, "netlist");
//plib::perftime_t<plib::exact_ticks> t;
nt.init();
{
auto t_guard(t.guard());
//plib::perftime_t<plib::exact_ticks> t;
if (!opt_verb())
nt.log().verbose.set_enabled(false);
if (opt_quiet())
nt.log().warning.set_enabled(false);
nt.init();
nt.read_netlist(opt_file(), opt_name(),
opt_logs(),
m_options, opt_rfolders());
if (!opt_verb())
nt.log().verbose.set_enabled(false);
if (opt_quiet())
nt.log().warning.set_enabled(false);
std::vector<input_t> inps = read_input(nt.setup(), opt_inp());
nt.read_netlist(opt_file(), opt_name(),
opt_logs(),
m_options, opt_rfolders());
inps = read_input(nt.setup(), opt_inp());
ttr = netlist::netlist_time::from_double(opt_ttr());
}
netlist::netlist_time ttr = netlist::netlist_time::from_double(opt_ttr());
t.stop();
pout("startup time ==> {1:5.3f}\n", t.as_seconds() );
t.reset();
t.start();
// FIXME: error handling
if (opt_loadstate.was_specified())
{
plib::pifilestream strm(opt_loadstate());
plib::pbinary_reader reader(strm);
std::vector<char> loadstate;
reader.read(loadstate);
nt.load_state(loadstate);
pout("Loaded state, run will continue at {1:.6f}\n", nt.time().as_double());
}
unsigned pos = 0;
netlist::netlist_time nlt = nt.time();
while (pos < inps.size()
&& inps[pos].m_time < ttr
&& inps[pos].m_time >= nlt)
{
nt.process_queue(inps[pos].m_time - nlt);
inps[pos].setparam();
nlt = inps[pos].m_time;
pos++;
auto t_guard(t.guard());
// FIXME: error handling
if (opt_loadstate.was_specified())
{
plib::pifilestream strm(opt_loadstate());
plib::pbinary_reader reader(strm);
std::vector<char> loadstate;
reader.read(loadstate);
nt.load_state(loadstate);
pout("Loaded state, run will continue at {1:.6f}\n", nt.time().as_double());
}
unsigned pos = 0;
while (pos < inps.size()
&& inps[pos].m_time < ttr
&& inps[pos].m_time >= nlt)
{
nt.process_queue(inps[pos].m_time - nlt);
inps[pos].setparam();
nlt = inps[pos].m_time;
pos++;
}
pout("runnning ...\n");
if (ttr > nlt)
nt.process_queue(ttr - nlt);
else
{
pout("end time {1:.6f} less than saved time {2:.6f}\n",
ttr.as_double(), nlt.as_double());
ttr = nlt;
}
if (opt_savestate.was_specified())
{
auto savestate = nt.save_state();
plib::pofilestream strm(opt_savestate());
plib::pbinary_writer writer(strm);
writer.write(savestate);
}
nt.stop();
}
pout("runnning ...\n");
if (ttr > nlt)
nt.process_queue(ttr - nlt);
else
{
pout("end time {1:.6f} less than saved time {2:.6f}\n",
ttr.as_double(), nlt.as_double());
ttr = nlt;
}
if (opt_savestate.was_specified())
{
auto savestate = nt.save_state();
plib::pofilestream strm(opt_savestate());
plib::pbinary_writer writer(strm);
writer.write(savestate);
}
nt.stop();
t.stop();
double emutime = t.as_seconds();
pout("{1:f} seconds emulation took {2:f} real time ==> {3:5.2f}%\n",
(ttr - nlt).as_double(), emutime,

View File

@ -302,7 +302,7 @@ void NETLIB_NAME(solver)::post_start()
else
ms = create_solver<double, 2>(2, sname);
break;
#if 0
#if 1
case 3:
ms = create_solver<double, 3>(3, sname);
break;

View File

@ -1703,7 +1703,7 @@ CIRCUIT_LAYOUT( breakout )
NET_C(GND, D9.1, D9.2, D9.13, D9.3, D9.4, D9.5)
#if 1
// 158% -- manually optimized
// 163% -- manually optimized
HINT(B6.s3, NO_DEACTIVATE)
HINT(C4.s3, NO_DEACTIVATE)
HINT(C4.s4, NO_DEACTIVATE)
@ -1729,10 +1729,10 @@ CIRCUIT_LAYOUT( breakout )
HINT(N7.s3, NO_DEACTIVATE)
#else
// 152% hints provided by log output
// 167% hints provided by log output - manually optimized
HINT(M4.s2, NO_DEACTIVATE) // 29.001761 197676 6816
HINT(M3.s3, NO_DEACTIVATE) // inf 129571 0
HINT(N7.s3, NO_DEACTIVATE) // inf 7850387 0
HINT(N7.s3, NO_DEACTIVATE) // inf 7850387 0 xx
HINT(M3.s2, NO_DEACTIVATE) // 23.234535 395870 17038
HINT(M3.s1, NO_DEACTIVATE) // 14.500880 197676 13632
HINT(L7.s3, NO_DEACTIVATE) // 122672.000000 122672 1
@ -1741,30 +1741,28 @@ CIRCUIT_LAYOUT( breakout )
HINT(K7.s3, NO_DEACTIVATE) // 122672.000000 122672 1
HINT(K7.s2, NO_DEACTIVATE) // 122673.000000 122673 1
HINT(K7.s1, NO_DEACTIVATE) // 122673.000000 122673 1
HINT(K4.s4, NO_DEACTIVATE) // 1438.774735 4202661 2921
HINT(K4.s2, NO_DEACTIVATE) // 3.939380 847790 215209
HINT(E2.s2, NO_DEACTIVATE) // 108.050000 315506 2920
HINT(K4.s4, NO_DEACTIVATE) // 1438.774735 4202661 2921 xx
HINT(K4.s2, NO_DEACTIVATE) // 3.939380 847790 215209 xx
HINT(E2.s2, NO_DEACTIVATE) // 108.050000 315506 2920 xx
HINT(L7.s4, NO_DEACTIVATE) // 122672.000000 122672 1
HINT(E9.s6, NO_DEACTIVATE) // inf 129571 0
HINT(J2.s6, NO_DEACTIVATE) // 493.408951 959187 1944
//HINT(J2.s6, NO_DEACTIVATE) // 493.408951 959187 1944
HINT(C5.s3, NO_DEACTIVATE) // inf 195514 0
HINT(M3.s4, NO_DEACTIVATE) // 27.744898 418726 15092
HINT(M3.s4, NO_DEACTIVATE) // 27.744898 418726 15092 xx
HINT(J8.s1, NO_DEACTIVATE) // 40890.000000 122670 3
HINT(E3.s2, NO_DEACTIVATE) // 203581.000000 203581 1
HINT(M9.s4, NO_DEACTIVATE) // inf 323268 0
HINT(L4.s2, NO_DEACTIVATE) // 7.290053 1192536 163584
HINT(J3.s4, NO_DEACTIVATE) // 393.639951 957726 2433
//HINT(L4.s2, NO_DEACTIVATE) // 7.290053 1192536 163584
HINT(J3.s4, NO_DEACTIVATE) // 393.639951 957726 2433 xx
HINT(L7.s1, NO_DEACTIVATE) // inf 122672 0
HINT(F2.s1, NO_DEACTIVATE) // 286289.000000 286289 1
HINT(M8.s1, NO_DEACTIVATE) // 129571.000000 129571 1
HINT(J7.s2, NO_DEACTIVATE) // inf 122672 0
HINT(H2.s1, NO_DEACTIVATE) // 393.839704 958212 2433
HINT(H3.s1, NO_DEACTIVATE) // 3.932473 850122 216180
//HINT(H2.s1, NO_DEACTIVATE) // 393.839704 958212 2433
HINT(H3.s1, NO_DEACTIVATE) // 3.932473 850122 216180 xx
HINT(J2.s5, NO_DEACTIVATE) // 26.140344 203581 7788
HINT(J7.s1, NO_DEACTIVATE) // inf 122672 0
HINT(J8.s3, NO_DEACTIVATE) // 40890.000000 122670 3
#endif
CIRCUIT_LAYOUT_END