/* * yosys -- Yosys Open SYnthesis Suite * * Copyright (C) 2012 Claire Xenia Wolf * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * */ #ifndef CONSTEVAL_H #define CONSTEVAL_H #include "kernel/rtlil.h" #include "kernel/sigtools.h" #include "kernel/celltypes.h" #include "kernel/macc.h" YOSYS_NAMESPACE_BEGIN struct ConstEval { RTLIL::Module *module; SigMap assign_map; SigMap values_map; SigPool stop_signals; SigSet sig2driver; std::set busy; std::vector stack; RTLIL::State defaultval; ConstEval(RTLIL::Module *module, RTLIL::State defaultval = RTLIL::State::Sm) : module(module), assign_map(module), defaultval(defaultval) { CellTypes ct; ct.setup_internals(); ct.setup_stdcells(); for (auto &it : module->cells_) { if (!ct.cell_known(it.second->type)) continue; for (auto &it2 : it.second->connections()) if (ct.cell_output(it.second->type, it2.first)) sig2driver.insert(assign_map(it2.second), it.second); } } void clear() { values_map.clear(); stop_signals.clear(); } void push() { stack.push_back(values_map); } void pop() { values_map.swap(stack.back()); stack.pop_back(); } void set(RTLIL::SigSpec sig, RTLIL::Const value) { assign_map.apply(sig); #ifndef NDEBUG RTLIL::SigSpec current_val = values_map(sig); for (int i = 0; i < GetSize(current_val); i++) log_assert(current_val[i].wire != NULL || current_val[i] == value.bits[i]); #endif values_map.add(sig, RTLIL::SigSpec(value)); } void stop(RTLIL::SigSpec sig) { assign_map.apply(sig); stop_signals.add(sig); } bool eval(RTLIL::Cell *cell, RTLIL::SigSpec &undef) { if (cell->type == ID($lcu)) { RTLIL::SigSpec sig_p = cell->getPort(ID::P); RTLIL::SigSpec sig_g = cell->getPort(ID::G); RTLIL::SigSpec sig_ci = cell->getPort(ID::CI); RTLIL::SigSpec sig_co = values_map(assign_map(cell->getPort(ID::CO))); if (sig_co.is_fully_const()) return true; if (!eval(sig_p, undef, cell)) return false; if (!eval(sig_g, undef, cell)) return false; if (!eval(sig_ci, undef, cell)) return false; if (sig_p.is_fully_def() && sig_g.is_fully_def() && sig_ci.is_fully_def()) { RTLIL::Const coval(RTLIL::Sx, GetSize(sig_co)); bool carry = sig_ci.as_bool(); for (int i = 0; i < GetSize(coval); i++) { carry = (sig_g[i] == State::S1) || (sig_p[i] == RTLIL::S1 && carry); coval.bits[i] = carry ? State::S1 : State::S0; } set(sig_co, coval); } else set(sig_co, RTLIL::Const(RTLIL::Sx, GetSize(sig_co))); return true; } RTLIL::SigSpec sig_a, sig_b, sig_s, sig_y; log_assert(cell->hasPort(ID::Y)); sig_y = values_map(assign_map(cell->getPort(ID::Y))); if (sig_y.is_fully_const()) return true; if (cell->hasPort(ID::S)) { sig_s = cell->getPort(ID::S); } if (cell->hasPort(ID::A)) sig_a = cell->getPort(ID::A); if (cell->hasPort(ID::B)) sig_b = cell->getPort(ID::B); if (cell->type.in(ID($mux), ID($pmux), ID($_MUX_), ID($_NMUX_))) { std::vector y_candidates; int count_set_s_bits = 0; if (!eval(sig_s, undef, cell)) return false; for (int i = 0; i < sig_s.size(); i++) { RTLIL::State s_bit = sig_s.extract(i, 1).as_const().bits.at(0); RTLIL::SigSpec b_slice = sig_b.extract(sig_y.size()*i, sig_y.size()); if (s_bit == RTLIL::State::Sx || s_bit == RTLIL::State::S1) y_candidates.push_back(b_slice); if (s_bit == RTLIL::State::S1) count_set_s_bits++; } if (count_set_s_bits == 0) y_candidates.push_back(sig_a); std::vector y_values; log_assert(y_candidates.size() > 0); for (auto &yc : y_candidates) { if (!eval(yc, undef, cell)) return false; if (cell->type == ID($_NMUX_)) y_values.push_back(RTLIL::const_not(yc.as_const(), Const(), false, false, GetSize(yc))); else y_values.push_back(yc.as_const()); } if (y_values.size() > 1) { std::vector master_bits = y_values.at(0).bits; for (size_t i = 1; i < y_values.size(); i++) { std::vector &slave_bits = y_values.at(i).bits; log_assert(master_bits.size() == slave_bits.size()); for (size_t j = 0; j < master_bits.size(); j++) if (master_bits[j] != slave_bits[j]) master_bits[j] = RTLIL::State::Sx; } set(sig_y, RTLIL::Const(master_bits)); } else set(sig_y, y_values.front()); } else if (cell->type == ID($bmux)) { if (!eval(sig_s, undef, cell)) return false; if (sig_s.is_fully_def()) { int sel = sig_s.as_int(); int width = GetSize(sig_y); SigSpec res = sig_a.extract(sel * width, width); if (!eval(res, undef, cell)) return false; set(sig_y, res.as_const()); } else { if (!eval(sig_a, undef, cell)) return false; set(sig_y, const_bmux(sig_a.as_const(), sig_s.as_const())); } } else if (cell->type == ID($demux)) { if (!eval(sig_a, undef, cell)) return false; if (sig_a.is_fully_zero()) { set(sig_y, Const(0, GetSize(sig_y))); } else { if (!eval(sig_s, undef, cell)) return false; set(sig_y, const_demux(sig_a.as_const(), sig_s.as_const())); } } else if (cell->type == ID($fa)) { RTLIL::SigSpec sig_c = cell->getPort(ID::C); RTLIL::SigSpec sig_x = cell->getPort(ID::X); int width = GetSize(sig_c); if (!eval(sig_a, undef, cell)) return false; if (!e
/*
    ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.

    This file is part of ChibiOS/RT.

    ChibiOS/RT is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.

    ChibiOS/RT is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <ch.h>

#include "test.h"

#if CH_USE_CONDVARS && CH_USE_MUTEXES

static Mutex m1;
static CondVar c1;

static char *cond1_gettest(void) {

  return "CondVar, signal test";
}

static void cond1_setup(void) {

  chCondInit(&c1);
  chMtxInit(&m1);
}

static void cond1_teardown(void) {
}

static msg_t thread1(void *p) {

  chMtxLock(&m1);
  chCondWait(&c1);
  test_emit_token(*(char *)p);
  chMtxUnlock();
  return 0;
}

static void cond1_execute(void) {

  // Bacause priority inheritance.
  tprio_t prio = chThdGetPriority();
  threads[0] = chThdCreateStatic(wa[0], WA_SIZE, prio+1, thread1, "E");
  threads[1] = chThdCreateStatic(wa[1], WA_SIZE, prio+2, thread1, "D");
  threads[2] = chThdCreateStatic(wa[2], WA_SIZE, prio+3, thread1, "C");
  threads[3] = chThdCreateStatic(wa[3], WA_SIZE, prio+4, thread1, "B");
  threads[4] = chThdCreateStatic(wa[4], WA_SIZE, prio+5, thread1, "A");
  test_assert(prio == chThdGetPriority(), "priority return failure");
  chCondSignal(&c1);
  chCondSignal(&c1);
  chCondSignal(&c1);
  chCondSignal(&c1);
  chCondSignal(&c1);
  test_wait_threads();
  test_assert_sequence("ABCDE");
}

const struct testcase testcond1 = {
  cond1_gettest,
  cond1_setup,
  cond1_teardown,
  cond1_execute
};

static char *cond2_gettest(void) {

  return "CondVar, broadcast test";
}

static void cond2_execute(void) {

  // Bacause priority inheritance.
  tprio_t prio = chThdGetPriority();
  threads[0] = chThdCreateStatic(wa[0], WA_SIZE, prio+1, thread1, "E");
  threads[1] = chThdCreateStatic(wa[1], WA_SIZE, prio+2, thread1, "D");
  threads[2] = chThdCreateStatic(wa[2], WA_SIZE, prio+3, thread1, "C");
  threads[3] = chThdCreateStatic(wa[3], WA_SIZE, prio+4, thread1, "B");
  threads[4] = chThdCreateStatic(wa[4], WA_SIZE, prio+5, thread1, "A");
  test_assert(prio == chThdGetPriority(), "priority return failure");
  chCondBroadcast(&c1);
  test_wait_threads();
  test_assert_sequence("ABCDE");
}

const struct testcase testcond2 = {
  cond2_gettest,
  cond1_setup,
  cond1_teardown,
  cond2_execute
};

#endif /* defined(CH_USE_CONDVARS) && defined(CH_USE_MUTEXES) */