mirror of
https://github.com/YosysHQ/yosys
synced 2026-02-14 04:41:48 +00:00
Merge 5a613fc457 into b890b1b43f
This commit is contained in:
commit
a4b29b4179
24 changed files with 641 additions and 107 deletions
|
|
@ -95,7 +95,7 @@ bool VERILOG_BACKEND::id_is_verilog_escaped(const std::string &str) {
|
|||
|
||||
PRIVATE_NAMESPACE_BEGIN
|
||||
|
||||
bool verbose, norename, noattr, attr2comment, noexpr, nodec, nohex, nostr, extmem, defparam, decimal, siminit, systemverilog, simple_lhs, noparallelcase;
|
||||
bool verbose, norename, noattr, attr2comment, noexpr, nodec, nohex, nostr, extmem, defparam, decimal, siminit, systemverilog, simple_lhs, noparallelcase, wreck;
|
||||
int auto_name_counter, auto_name_offset, auto_name_digits, extmem_counter;
|
||||
dict<RTLIL::IdString, int> auto_name_map;
|
||||
std::set<RTLIL::IdString> reg_wires;
|
||||
|
|
@ -2554,6 +2554,10 @@ struct VerilogBackend : public Backend {
|
|||
log(" only write selected modules. modules must be selected entirely or\n");
|
||||
log(" not at all.\n");
|
||||
log("\n");
|
||||
log(" -wreck\n");
|
||||
log(" wreck your design by running required preparation passes\n");
|
||||
log(" on it, instead of a copy. Used to be the default.\n");
|
||||
log("\n");
|
||||
log(" -v\n");
|
||||
log(" verbose output (print new names of all renamed wires and cells)\n");
|
||||
log("\n");
|
||||
|
|
@ -2666,6 +2670,10 @@ struct VerilogBackend : public Backend {
|
|||
verbose = true;
|
||||
continue;
|
||||
}
|
||||
if (arg == "-wreck") {
|
||||
wreck = true;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
extra_args(f, filename, args, argidx);
|
||||
|
|
@ -2676,15 +2684,31 @@ struct VerilogBackend : public Backend {
|
|||
extmem_prefix = filename.substr(0, filename.rfind('.'));
|
||||
}
|
||||
|
||||
RTLIL::Design *original_design;
|
||||
if (!wreck) {
|
||||
// FIXME shamefully copied out of design.cc
|
||||
RTLIL::Design * design_copy = new RTLIL::Design;
|
||||
|
||||
for (auto mod : design->modules())
|
||||
design_copy->add(mod->clone());
|
||||
|
||||
design_copy->selection_stack = design->selection_stack;
|
||||
design_copy->selection_vars = design->selection_vars;
|
||||
design_copy->selected_active_module = design->selected_active_module;
|
||||
original_design = design;
|
||||
design = design_copy;
|
||||
}
|
||||
|
||||
log_push();
|
||||
if (!noexpr) {
|
||||
Pass::call(design, "bmuxmap");
|
||||
Pass::call(design, "demuxmap");
|
||||
Pass::call(design, "simplemap t:$priority");
|
||||
}
|
||||
Pass::call(design, "clean_zerowidth");
|
||||
log_pop();
|
||||
|
||||
design->sort_modules();
|
||||
design->sort_modules();
|
||||
|
||||
*f << stringf("/* Generated by %s */\n", yosys_maybe_version());
|
||||
|
||||
|
|
@ -2701,6 +2725,11 @@ struct VerilogBackend : public Backend {
|
|||
dump_module(*f, "", module);
|
||||
}
|
||||
|
||||
if (!wreck) {
|
||||
RTLIL::Design * design_copy = design;
|
||||
design = original_design;
|
||||
delete design_copy;
|
||||
}
|
||||
auto_name_map.clear();
|
||||
reg_wires.clear();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -658,6 +658,28 @@ RTLIL::Const RTLIL::const_bmux(const RTLIL::Const &arg1, const RTLIL::Const &arg
|
|||
return t;
|
||||
}
|
||||
|
||||
RTLIL::Const RTLIL::const_priority(const RTLIL::Const &arg, const RTLIL::Const &polarity)
|
||||
{
|
||||
std::vector<RTLIL::State> t;
|
||||
RTLIL::State previous;
|
||||
if (GetSize(arg)) {
|
||||
RTLIL::State s = arg.at(0);
|
||||
t.push_back(s);
|
||||
previous = polarity[0] ? s : const_not(s, Const(), false, false, 1)[0];
|
||||
}
|
||||
for (int i = 1; i < GetSize(arg); i++)
|
||||
{
|
||||
RTLIL::State s = arg.at(i);
|
||||
RTLIL::State is_active = const_xnor(s, polarity[i], false, false, 1)[0];
|
||||
RTLIL::State next = const_or(is_active, previous, false, false, 1)[0];
|
||||
RTLIL::State inactive_polarity = const_not(polarity[i], Const(), false, false, 1)[0];
|
||||
RTLIL::State y = const_mux(s, inactive_polarity, previous)[0];
|
||||
t.push_back(y);
|
||||
previous = next;
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
RTLIL::Const RTLIL::const_demux(const RTLIL::Const &arg1, const RTLIL::Const &arg2)
|
||||
{
|
||||
int width = GetSize(arg1);
|
||||
|
|
|
|||
|
|
@ -501,6 +501,27 @@ Aig::Aig(Cell *cell)
|
|||
goto optimize;
|
||||
}
|
||||
|
||||
if (cell->type == ID($priority))
|
||||
{
|
||||
int width = GetSize(cell->getPort(ID::Y));
|
||||
RTLIL::Const polarity = cell->getParam(ID::POLARITY);
|
||||
vector<int> A = mk.inport_vec(ID::A, width);
|
||||
vector<int> Y;
|
||||
int any_previous_active;
|
||||
if (width) {
|
||||
any_previous_active = polarity[0] ? A[0] : mk.not_gate(A[0]);
|
||||
Y.push_back(A[0]);
|
||||
}
|
||||
for (int i = 1; i < width; i++) {
|
||||
int inactive_val = mk.bool_node(!polarity[i]);
|
||||
Y.push_back(mk.mux_gate(A[i], inactive_val, any_previous_active));
|
||||
int is_active = mk.xnor_gate(inactive_val, A[i]);
|
||||
any_previous_active = mk.or_gate(any_previous_active, is_active);
|
||||
}
|
||||
mk.outport_vec(Y, ID::Y);
|
||||
goto optimize;
|
||||
}
|
||||
|
||||
name.clear();
|
||||
return;
|
||||
|
||||
|
|
|
|||
|
|
@ -118,7 +118,7 @@ struct CellTypes
|
|||
void setup_internals_eval()
|
||||
{
|
||||
std::vector<RTLIL::IdString> unary_ops = {
|
||||
ID($not), ID($pos), ID($buf), ID($neg),
|
||||
ID($not), ID($pos), ID($buf), ID($neg), ID($priority),
|
||||
ID($reduce_and), ID($reduce_or), ID($reduce_xor), ID($reduce_xnor), ID($reduce_bool),
|
||||
ID($logic_not), ID($slice), ID($lut), ID($sop)
|
||||
};
|
||||
|
|
@ -509,6 +509,11 @@ struct CellTypes
|
|||
return default_ret;
|
||||
}
|
||||
|
||||
if (cell->type == ID($priority))
|
||||
{
|
||||
return const_priority(arg1, cell->getParam(ID::POLARITY));
|
||||
}
|
||||
|
||||
bool signed_a = cell->parameters.count(ID::A_SIGNED) > 0 && cell->parameters[ID::A_SIGNED].as_bool();
|
||||
bool signed_b = cell->parameters.count(ID::B_SIGNED) > 0 && cell->parameters[ID::B_SIGNED].as_bool();
|
||||
int result_len = cell->parameters.count(ID::Y_WIDTH) > 0 ? cell->parameters[ID::Y_WIDTH].as_int() : -1;
|
||||
|
|
|
|||
|
|
@ -259,6 +259,7 @@ X($pmux)
|
|||
X($pos)
|
||||
X($pow)
|
||||
X($print)
|
||||
X($priority)
|
||||
X($recrem)
|
||||
X($reduce_and)
|
||||
X($reduce_bool)
|
||||
|
|
@ -614,6 +615,7 @@ X(PATTERN)
|
|||
X(PCIN)
|
||||
X(PIPELINE_16x16_MULT_REG1)
|
||||
X(PIPELINE_16x16_MULT_REG2)
|
||||
X(POLARITY)
|
||||
X(PORTID)
|
||||
X(PORT_A1_ADDR)
|
||||
X(PORT_A1_CLK)
|
||||
|
|
|
|||
|
|
@ -2654,6 +2654,14 @@ namespace {
|
|||
check_expected();
|
||||
return;
|
||||
}
|
||||
if (cell->type.in(ID($priority))) {
|
||||
param(ID::WIDTH);
|
||||
param(ID::POLARITY);
|
||||
port(ID::A, param(ID::WIDTH));
|
||||
port(ID::Y, param(ID::WIDTH));
|
||||
check_expected();
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* Checklist for adding internal cell types
|
||||
* ========================================
|
||||
|
|
@ -3971,6 +3979,14 @@ RTLIL::Cell* RTLIL::Module::addDlatchsr(RTLIL::IdString name, const RTLIL::SigSp
|
|||
cell->set_src_attribute(src);
|
||||
return cell;
|
||||
}
|
||||
RTLIL::Cell* RTLIL::Module::addPriority(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_y, const std::string &src)
|
||||
{
|
||||
RTLIL::Cell *cell = addCell(name, ID($priority));
|
||||
cell->setPort(ID::A, sig_a);
|
||||
cell->setPort(ID::Y, sig_y);
|
||||
cell->set_src_attribute(src);
|
||||
return cell;
|
||||
}
|
||||
|
||||
RTLIL::Cell* RTLIL::Module::addSrGate(RTLIL::IdString name, const RTLIL::SigSpec &sig_set, const RTLIL::SigSpec &sig_clr,
|
||||
const RTLIL::SigSpec &sig_q, bool set_polarity, bool clr_polarity, const std::string &src)
|
||||
|
|
@ -4548,7 +4564,7 @@ void RTLIL::Cell::fixup_parameters(bool set_a_signed, bool set_b_signed)
|
|||
return;
|
||||
}
|
||||
|
||||
if (type == ID($lut) || type == ID($sop)) {
|
||||
if (type == ID($lut) || type == ID($sop) || type == ID($priority)) {
|
||||
parameters[ID::WIDTH] = GetSize(connections_[ID::A]);
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -848,6 +848,7 @@ namespace RTLIL {
|
|||
RTLIL::Const const_pmux (const RTLIL::Const &arg1, const RTLIL::Const &arg2, const RTLIL::Const &arg3);
|
||||
RTLIL::Const const_bmux (const RTLIL::Const &arg1, const RTLIL::Const &arg2);
|
||||
RTLIL::Const const_demux (const RTLIL::Const &arg1, const RTLIL::Const &arg2);
|
||||
RTLIL::Const const_priority (const RTLIL::Const &arg, const RTLIL::Const &polarity);
|
||||
|
||||
RTLIL::Const const_bweqx (const RTLIL::Const &arg1, const RTLIL::Const &arg2);
|
||||
RTLIL::Const const_bwmux (const RTLIL::Const &arg1, const RTLIL::Const &arg2, const RTLIL::Const &arg3);
|
||||
|
|
@ -2263,6 +2264,8 @@ public:
|
|||
RTLIL::Cell* addAdlatch (RTLIL::IdString name, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_arst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, RTLIL::Const arst_value, bool en_polarity = true, bool arst_polarity = true, const std::string &src = "");
|
||||
RTLIL::Cell* addDlatchsr (RTLIL::IdString name, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_set, const RTLIL::SigSpec &sig_clr, RTLIL::SigSpec sig_d, const RTLIL::SigSpec &sig_q, bool en_polarity = true, bool set_polarity = true, bool clr_polarity = true, const std::string &src = "");
|
||||
|
||||
RTLIL::Cell* addPriority (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_y, const std::string &src = "");
|
||||
|
||||
RTLIL::Cell* addBufGate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_y, const std::string &src = "");
|
||||
RTLIL::Cell* addNotGate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_y, const std::string &src = "");
|
||||
RTLIL::Cell* addAndGate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SigBit &sig_y, const std::string &src = "");
|
||||
|
|
|
|||
|
|
@ -430,6 +430,57 @@ bool SatGen::importCell(RTLIL::Cell *cell, int timestep)
|
|||
return true;
|
||||
}
|
||||
|
||||
if (cell->type == ID($priority))
|
||||
{
|
||||
std::vector<int> a = importDefSigSpec(cell->getPort(ID::A), timestep);
|
||||
std::vector<int> y = importDefSigSpec(cell->getPort(ID::Y), timestep);
|
||||
std::vector<int> yy = model_undef ? ez->vec_var(y.size()) : y;
|
||||
|
||||
const Const& polarity = cell->getParam(ID::POLARITY);
|
||||
|
||||
std::vector<int> active_so_far;
|
||||
if (a.size()) {
|
||||
active_so_far.push_back(polarity[0] ? a[0] : ez->NOT(a[0]));
|
||||
ez->assume(ez->IFF(yy[0], a[0]));
|
||||
}
|
||||
for (size_t i = 1; i < a.size(); i++) {
|
||||
int inactive_val = !polarity[i] ? ez->CONST_TRUE : ez->CONST_FALSE;
|
||||
int active_val = polarity[i] ? ez->CONST_TRUE : ez->CONST_FALSE;
|
||||
ez->assume(ez->IFF(yy[i], ez->ITE(active_so_far.back(), inactive_val, a[i])));
|
||||
active_so_far.push_back(ez->OR(active_so_far.back(), ez->IFF(a[i], active_val)));
|
||||
}
|
||||
if (model_undef) {
|
||||
std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID::A), timestep);
|
||||
std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID::Y), timestep);
|
||||
|
||||
int any_previous_undef;
|
||||
if (a.size()) {
|
||||
any_previous_undef = undef_a[0];
|
||||
ez->assume(ez->IFF(undef_y[0], undef_a[0]));
|
||||
}
|
||||
for (size_t i = 1; i < a.size(); i++) {
|
||||
int inactive_val = !polarity[i] ? ez->CONST_TRUE : ez->CONST_FALSE;
|
||||
int is_active = ez->XOR(inactive_val, a[i]);
|
||||
int is_not_inactive = ez->OR(is_active, undef_a[i]);
|
||||
int is_not_active = ez->OR(ez->NOT(is_active), undef_a[i]);
|
||||
|
||||
// $mux
|
||||
int undef_because_s = ez->AND(any_previous_undef, is_not_inactive);
|
||||
int undef_because_a = ez->AND(ez->OR(any_previous_undef, ez->NOT(active_so_far[i-1])), undef_a[i]);
|
||||
int undef = ez->OR(undef_because_s, undef_because_a);
|
||||
ez->assume(ez->IFF(undef_y[i], undef));
|
||||
|
||||
// $or
|
||||
int next_previous_undef_because_previous = ez->AND(any_previous_undef, is_not_active);
|
||||
int next_previous_undef_because_a = ez->AND(ez->NOT(active_so_far[i-1]), undef_a[i]);
|
||||
any_previous_undef = ez->OR(next_previous_undef_because_previous, next_previous_undef_because_a);
|
||||
}
|
||||
undefGating(y, yy, undef_y);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (cell->type.in(ID($pos), ID($buf), ID($neg)))
|
||||
{
|
||||
std::vector<int> a = importDefSigSpec(cell->getPort(ID::A), timestep);
|
||||
|
|
|
|||
|
|
@ -17,15 +17,31 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include "backends/rtlil/rtlil_backend.h"
|
||||
#include "kernel/register.h"
|
||||
#include "kernel/rtlil.h"
|
||||
#include "kernel/sigtools.h"
|
||||
#include "kernel/consteval.h"
|
||||
#include "kernel/log.h"
|
||||
#include "kernel/yosys_common.h"
|
||||
#include <optional>
|
||||
#include <sstream>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
USING_YOSYS_NAMESPACE
|
||||
|
||||
struct BitRule {
|
||||
SigBit trig;
|
||||
bool trig_polarity; // true = active high, false = active low
|
||||
bool effect; // true = set, false = reset
|
||||
|
||||
bool operator==(const BitRule& other) const { return trig == other.trig && trig_polarity == other.trig_polarity && effect == other.effect; }
|
||||
[[nodiscard]] Hasher hash_into(Hasher h) const { // No, this fluff doesn't deserve more lines. It's not meant to be read.
|
||||
h.eat(trig); h.eat(trig_polarity); h.eat(effect); return h; }
|
||||
};
|
||||
template<> struct std::hash<std::vector<BitRule>> {std::size_t operator()(const std::vector<BitRule>& r) const noexcept { Hasher h; for (auto& rr : r) h.eat(rr); return (size_t)h.yield(); } };
|
||||
|
||||
PRIVATE_NAMESPACE_BEGIN
|
||||
|
||||
RTLIL::SigSpec find_any_lvalue(const RTLIL::Process *proc)
|
||||
|
|
@ -53,13 +69,23 @@ RTLIL::SigSpec find_any_lvalue(const RTLIL::Process *proc)
|
|||
return lvalue;
|
||||
}
|
||||
|
||||
void gen_dffsr_complex(RTLIL::Module *mod, RTLIL::SigSpec sig_d, RTLIL::SigSpec sig_q, RTLIL::SigSpec clk, bool clk_polarity,
|
||||
std::vector<std::pair<RTLIL::SigSpec, RTLIL::SyncRule*>> &async_rules, RTLIL::Process *proc)
|
||||
struct DSigs {
|
||||
RTLIL::SigSpec d;
|
||||
RTLIL::SigSpec q;
|
||||
RTLIL::SigSpec clk;
|
||||
};
|
||||
using Rules = std::vector<std::pair<RTLIL::SigSpec, RTLIL::SyncRule*>>;
|
||||
|
||||
/**
|
||||
* Generates odd $dffsr wirh priority and ALOAD implemented with muxes
|
||||
*/
|
||||
void gen_dffsr_complex(RTLIL::Module *mod, DSigs sigs, bool clk_polarity,
|
||||
Rules &async_rules, RTLIL::Process *proc)
|
||||
{
|
||||
// A signal should be set/cleared if there is a load trigger that is enabled
|
||||
// such that the load value is 1/0 and it is the highest priority trigger
|
||||
RTLIL::SigSpec sig_sr_set = RTLIL::SigSpec(0, sig_d.size());
|
||||
RTLIL::SigSpec sig_sr_clr = RTLIL::SigSpec(0, sig_d.size());
|
||||
RTLIL::SigSpec sig_sr_set = RTLIL::SigSpec(0, sigs.d.size());
|
||||
RTLIL::SigSpec sig_sr_clr = RTLIL::SigSpec(0, sigs.d.size());
|
||||
|
||||
// Reverse iterate through the rules as the first ones are the highest priority
|
||||
// so need to be at the top of the mux trees
|
||||
|
|
@ -81,13 +107,189 @@ void gen_dffsr_complex(RTLIL::Module *mod, RTLIL::SigSpec sig_d, RTLIL::SigSpec
|
|||
std::stringstream sstr;
|
||||
sstr << "$procdff$" << (autoidx++);
|
||||
|
||||
RTLIL::Cell *cell = mod->addDffsr(sstr.str(), clk, sig_sr_set, sig_sr_clr, sig_d, sig_q, clk_polarity);
|
||||
RTLIL::Cell *cell = mod->addDffsr(sstr.str(), sigs.clk, sig_sr_set, sig_sr_clr, sigs.d, sigs.q, clk_polarity);
|
||||
cell->attributes = proc->attributes;
|
||||
|
||||
log(" created %s cell `%s' with %s edge clock and multiple level-sensitive resets.\n",
|
||||
cell->type.c_str(), cell->name.c_str(), clk_polarity ? "positive" : "negative");
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates $dffsr wirh $priority cells
|
||||
*/
|
||||
void gen_dffsr(RTLIL::Module *mod, DSigs sigs, bool clk_polarity,
|
||||
Rules &async_rules, ConstEval& ce, RTLIL::Process *proc)
|
||||
{
|
||||
RTLIL::SigSpec sig_sr_set;
|
||||
RTLIL::SigSpec sig_sr_clr;
|
||||
// nullopt rule = "this bit is not assigned to in this rule"
|
||||
std::vector<std::vector<std::optional<BitRule>>> bit_rules(sigs.d.size());
|
||||
// For checking consistent per-bit set/reset edges and bailing out on inconsistent
|
||||
std::optional<bool> set_pol;
|
||||
std::optional<bool> reset_pol;
|
||||
|
||||
for (auto it = async_rules.cbegin(); it != async_rules.cend(); it++)
|
||||
{
|
||||
const auto& [sync_value, rule] = *it;
|
||||
for (int i = 0; i < sigs.d.size(); i++) {
|
||||
log_assert(rule->signal.size() == 1);
|
||||
SigSpec value_bit = sync_value[i];
|
||||
if (sync_value[i] == sigs.q[i]) {
|
||||
log_debug("%s is %s\n", log_signal(sync_value[i]), log_signal(sigs.q[i]));
|
||||
while (bit_rules.size() <= (size_t) i)
|
||||
bit_rules.push_back({});
|
||||
bit_rules[i].push_back(std::nullopt);
|
||||
continue;
|
||||
}
|
||||
if (!ce.eval(value_bit)) {
|
||||
// ALOAD, mux tree time
|
||||
log_debug("non-const %s\n", log_signal(sync_value[i]));
|
||||
gen_dffsr_complex(mod, sigs, clk_polarity, async_rules, proc);
|
||||
return;
|
||||
}
|
||||
bool effect = ce.values_map(value_bit).as_const().as_bool();
|
||||
bool trig_pol = rule->type == RTLIL::SyncType::ST1;
|
||||
while (bit_rules.size() <= (size_t) i)
|
||||
bit_rules.push_back({});
|
||||
BitRule bit_rule {rule->signal[0], trig_pol, effect};
|
||||
bit_rules[i].push_back(bit_rule);
|
||||
|
||||
bool set_inconsistent = effect && set_pol && (*set_pol != trig_pol);
|
||||
bool reset_inconsistent = !effect && reset_pol && (*reset_pol != trig_pol);
|
||||
if (set_inconsistent || reset_inconsistent) {
|
||||
// Mixed polarities, mux tree time
|
||||
gen_dffsr_complex(mod, sigs, clk_polarity, async_rules, proc);
|
||||
return;
|
||||
}
|
||||
if (effect) {
|
||||
set_pol = trig_pol;
|
||||
} else {
|
||||
reset_pol = trig_pol;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (set_pol == std::nullopt || reset_pol == std::nullopt) {
|
||||
// set or reset never used, falling back to mux tree
|
||||
gen_dffsr_complex(mod, sigs, clk_polarity, async_rules, proc);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
struct Builder {
|
||||
using MaybeBitControl = std::pair<std::optional<SigBit>, std::optional<SigBit>>;
|
||||
std::unordered_map<std::vector<BitRule>, MaybeBitControl> map = {};
|
||||
RTLIL::Module* mod;
|
||||
RTLIL::Process* proc;
|
||||
bool set_pol, reset_pol;
|
||||
RTLIL::SigBit const_if_none(std::optional<SigBit> maybe, bool polarity) {
|
||||
if (maybe)
|
||||
return *maybe;
|
||||
// Set the control signal to be constantly inactive
|
||||
if (polarity)
|
||||
return set_pol ? RTLIL::State::S0 : RTLIL::State::S1;
|
||||
else
|
||||
return reset_pol ? RTLIL::State::S0 : RTLIL::State::S1;
|
||||
}
|
||||
Builder(RTLIL::Module* mod, RTLIL::Process* proc, bool s, bool r) : mod(mod), proc(proc), set_pol(s), reset_pol(r) {}
|
||||
std::pair<RTLIL::SigSpec, RTLIL::SigSpec> priority(const std::vector<BitRule>& applicable) {
|
||||
RTLIL::SigSpec bit_sets {};
|
||||
RTLIL::SigSpec bit_resets {};
|
||||
if (!applicable.size()) {
|
||||
return std::make_pair(bit_sets, bit_resets);
|
||||
} else if (applicable.size() == 1) {
|
||||
auto rule = applicable[0];
|
||||
if (rule.effect)
|
||||
bit_sets.append(rule.trig);
|
||||
else
|
||||
bit_resets.append(rule.trig);
|
||||
return std::make_pair(bit_sets, bit_resets);
|
||||
}
|
||||
RTLIL::Wire* prioritized = mod->addWire(NEW_ID, applicable.size());
|
||||
prioritized->attributes = proc->attributes;
|
||||
RTLIL::Cell* priority = mod->addPriority(NEW_ID, SigSpec(), prioritized);
|
||||
priority->attributes = proc->attributes;
|
||||
priority->setParam(ID::WIDTH, applicable.size());
|
||||
|
||||
RTLIL::SigSpec priority_in;
|
||||
std::vector<RTLIL::State> priority_pol;
|
||||
|
||||
// Construct applicable rules
|
||||
for (auto rule : applicable) {
|
||||
log_debug("if %s == %d then set %d\n", log_signal(rule.trig), rule.trig_polarity, rule.effect);
|
||||
priority_in.append(rule.trig);
|
||||
priority_pol.push_back(RTLIL::State(rule.trig_polarity));
|
||||
if (rule.effect)
|
||||
bit_sets.append(SigBit(prioritized, priority_in.size() - 1));
|
||||
else
|
||||
bit_resets.append(SigBit(prioritized, priority_in.size() - 1));
|
||||
}
|
||||
|
||||
priority->setPort(ID::A, priority_in);
|
||||
priority->setPort(ID::Y, prioritized); // fixup (previously zero-width)
|
||||
priority->setParam(ID::POLARITY, priority_pol);
|
||||
return std::make_pair(bit_sets, bit_resets);
|
||||
}
|
||||
std::pair<RTLIL::SigBit, RTLIL::SigBit> reduce(const std::pair<RTLIL::SigSpec, RTLIL::SigSpec>& unreduced) {
|
||||
const auto& [bit_sets, bit_resets] = unreduced;
|
||||
std::optional<SigBit> set, reset;
|
||||
if (bit_sets.size()) {
|
||||
if (bit_sets.size() == 1) {
|
||||
set = bit_sets[0];
|
||||
} else {
|
||||
set = mod->addWire(NEW_ID);
|
||||
set->wire->attributes = proc->attributes;
|
||||
// Polarities are required to be consistent, as guaranteed by check above buildere
|
||||
(set_pol ? mod->addReduceOr(NEW_ID, bit_sets, *set) : mod->addReduceAnd(NEW_ID, bit_sets, *set))->attributes = proc->attributes;
|
||||
}
|
||||
}
|
||||
if (bit_resets.size()) {
|
||||
if (bit_resets.size() == 1) {
|
||||
reset = bit_resets[0];
|
||||
} else {
|
||||
reset = mod->addWire(NEW_ID);
|
||||
reset->wire->attributes = proc->attributes;
|
||||
(reset_pol ? mod->addReduceOr(NEW_ID, bit_resets, *reset) : mod->addReduceAnd(NEW_ID, bit_resets, *reset))->attributes = proc->attributes;
|
||||
}
|
||||
}
|
||||
return std::make_pair(const_if_none(set, true), const_if_none(reset, false));
|
||||
}
|
||||
MaybeBitControl build(std::vector<std::optional<BitRule>>& rules) {
|
||||
std::vector<BitRule> applicable;
|
||||
for (auto rule : rules) {
|
||||
if (rule) {
|
||||
applicable.push_back(*rule);
|
||||
} else {
|
||||
log_debug("Unused bit due to no assignment to this bit from this rule\n");
|
||||
}
|
||||
}
|
||||
if (map.count(applicable)) {
|
||||
return map[applicable];
|
||||
}
|
||||
|
||||
auto priority_controls = priority(applicable);
|
||||
auto ret = reduce(priority_controls);
|
||||
map[applicable] = ret;
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
Builder builder(mod, proc, *set_pol, *reset_pol);
|
||||
for (int i = 0; i < sigs.d.size(); i++) {
|
||||
auto [set, reset] = builder.build(bit_rules[i]);
|
||||
sig_sr_set.append(*set);
|
||||
sig_sr_clr.append(*reset);
|
||||
}
|
||||
|
||||
std::stringstream sstr;
|
||||
sstr << "$procdff$" << (autoidx++);
|
||||
RTLIL::Cell *cell = mod->addDffsr(sstr.str(), sigs.clk, sig_sr_set, sig_sr_clr, sigs.d, sigs.q, clk_polarity);
|
||||
cell->attributes = proc->attributes;
|
||||
cell->setParam(ID::SET_POLARITY, Const(*set_pol, 1));
|
||||
cell->setParam(ID::CLR_POLARITY, Const(*reset_pol, 1));
|
||||
log(" created %s cell `%s' with %s edge clock and multiple level-sensitive resets.\n",
|
||||
cell->type.c_str(), cell->name.c_str(), clk_polarity ? "positive" : "negative");
|
||||
}
|
||||
|
||||
void gen_aldff(RTLIL::Module *mod, RTLIL::SigSpec sig_in, RTLIL::SigSpec sig_set, RTLIL::SigSpec sig_out,
|
||||
bool clk_polarity, bool set_polarity, RTLIL::SigSpec clk, RTLIL::SigSpec set, RTLIL::Process *proc)
|
||||
{
|
||||
|
|
@ -261,7 +463,9 @@ void proc_dff(RTLIL::Module *mod, RTLIL::Process *proc, ConstEval &ce)
|
|||
if (async_rules.size() > 1)
|
||||
{
|
||||
log_warning("Complex async reset for dff `%s'.\n", log_signal(sig));
|
||||
gen_dffsr_complex(mod, insig, sig, sync_edge->signal, sync_edge->type == RTLIL::SyncType::STp, async_rules, proc);
|
||||
DSigs sigs {insig, sig, sync_edge->signal};
|
||||
bool clk_pol = sync_edge->type == RTLIL::SyncType::STp;
|
||||
gen_dffsr(mod, sigs, clk_pol, async_rules, ce, proc);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -305,6 +509,7 @@ struct ProcDffPass : public Pass {
|
|||
log_header(design, "Executing PROC_DFF pass (convert process syncs to FFs).\n");
|
||||
|
||||
extra_args(args, 1, design);
|
||||
Pass::call(design, "dump");
|
||||
|
||||
for (auto mod : design->all_selected_modules()) {
|
||||
ConstEval ce(mod);
|
||||
|
|
|
|||
|
|
@ -123,10 +123,14 @@ struct Clk2fflogicPass : public Pass {
|
|||
return module->Mux(NEW_ID, a, b, s);
|
||||
}
|
||||
SigSpec bitwise_sr(Module *module, SigSpec a, SigSpec s, SigSpec r, bool is_fine) {
|
||||
if (is_fine)
|
||||
return module->AndGate(NEW_ID, module->OrGate(NEW_ID, a, s), module->NotGate(NEW_ID, r));
|
||||
else
|
||||
return module->And(NEW_ID, module->Or(NEW_ID, a, s), module->Not(NEW_ID, r));
|
||||
if (is_fine) {
|
||||
return module->MuxGate(NEW_ID, module->AndGate(NEW_ID, module->OrGate(NEW_ID, a, s), module->NotGate(NEW_ID, r)), RTLIL::State::Sx, module->AndGate(NEW_ID, s, r));
|
||||
} else {
|
||||
std::vector<SigBit> y;
|
||||
for (int i = 0; i < a.size(); i++)
|
||||
y.push_back(module->MuxGate(NEW_ID, module->AndGate(NEW_ID, module->OrGate(NEW_ID, a[i], s[i]), module->NotGate(NEW_ID, r[i])), RTLIL::State::Sx, module->AndGate(NEW_ID, s[i], r[i])));
|
||||
return y;
|
||||
}
|
||||
}
|
||||
void execute(std::vector<std::string> args, RTLIL::Design *design) override
|
||||
{
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
*/
|
||||
|
||||
#include "simplemap.h"
|
||||
#include "kernel/rtlil.h"
|
||||
#include "kernel/sigtools.h"
|
||||
#include "kernel/ff.h"
|
||||
#include <stdlib.h>
|
||||
|
|
@ -27,11 +28,11 @@
|
|||
USING_YOSYS_NAMESPACE
|
||||
YOSYS_NAMESPACE_BEGIN
|
||||
|
||||
static void transfer_attr (Cell* to, const Cell* from, IdString attr) {
|
||||
static void transfer_attr (RTLIL::AttrObject* to, const RTLIL::AttrObject* from, IdString attr) {
|
||||
if (from->has_attribute(attr))
|
||||
to->attributes[attr] = from->attributes.at(attr);
|
||||
}
|
||||
static void transfer_src (Cell* to, const Cell* from) {
|
||||
static void transfer_src (RTLIL::AttrObject* to, const RTLIL::AttrObject* from) {
|
||||
transfer_attr(to, from, ID::src);
|
||||
}
|
||||
|
||||
|
|
@ -438,6 +439,37 @@ void simplemap_ff(RTLIL::Module *, RTLIL::Cell *cell)
|
|||
}
|
||||
}
|
||||
|
||||
void simplemap_priority(RTLIL::Module *module, RTLIL::Cell *cell)
|
||||
{
|
||||
int width = cell->getParam(ID::WIDTH).as_int();
|
||||
RTLIL::Const polarity = cell->getParam(ID::POLARITY);
|
||||
RTLIL::Wire* any_previous_active = module->addWire(NEW_ID, width);
|
||||
transfer_src(any_previous_active, cell);
|
||||
RTLIL::Wire* active = module->addWire(NEW_ID, width);
|
||||
transfer_src(active, cell);
|
||||
RTLIL::SigSpec a = cell->getPort(ID::A);
|
||||
RTLIL::SigSpec y = cell->getPort(ID::Y);
|
||||
if (width) {
|
||||
RTLIL::State active_val = polarity[0] ? RTLIL::State::S1 : RTLIL::State::S0;
|
||||
RTLIL::Cell* xnor = module->addXnorGate(NEW_ID, a[0], active_val, {RTLIL::SigBit(any_previous_active, 0)});
|
||||
transfer_src(xnor, cell);
|
||||
module->connect({y[0], a[0]});
|
||||
}
|
||||
for (int i = 1; i < width; i++) {
|
||||
RTLIL::State inactive_val = !polarity[i] ? RTLIL::State::S1 : RTLIL::State::S0;
|
||||
RTLIL::State active_val = polarity[i] ? RTLIL::State::S1 : RTLIL::State::S0;
|
||||
RTLIL::SigBit this_active = {active, i};
|
||||
RTLIL::SigBit active_so_far = {any_previous_active, i - 1};
|
||||
RTLIL::SigBit next_active_so_far = {any_previous_active, i};
|
||||
RTLIL::Cell* mux = module->addMuxGate(NEW_ID, a[i], inactive_val, active_so_far, y[i]);
|
||||
RTLIL::Cell* xnor = module->addXnorGate(NEW_ID, a[i], active_val, this_active);
|
||||
RTLIL::Cell* or_ = module->addOrGate(NEW_ID, active_so_far, this_active, next_active_so_far);
|
||||
transfer_src(xnor, cell);
|
||||
transfer_src(mux, cell);
|
||||
transfer_src(or_, cell);
|
||||
}
|
||||
}
|
||||
|
||||
void simplemap_get_mappers(dict<IdString, void(*)(RTLIL::Module*, RTLIL::Cell*)> &mappers)
|
||||
{
|
||||
mappers[ID($not)] = simplemap_not;
|
||||
|
|
@ -484,6 +516,7 @@ void simplemap_get_mappers(dict<IdString, void(*)(RTLIL::Module*, RTLIL::Cell*)>
|
|||
mappers[ID($dlatch)] = simplemap_ff;
|
||||
mappers[ID($adlatch)] = simplemap_ff;
|
||||
mappers[ID($dlatchsr)] = simplemap_ff;
|
||||
mappers[ID($priority)] = simplemap_priority;
|
||||
}
|
||||
|
||||
void simplemap(RTLIL::Module *module, RTLIL::Cell *cell)
|
||||
|
|
|
|||
|
|
@ -136,6 +136,27 @@ static RTLIL::Cell* create_gold_module(RTLIL::Design *design, RTLIL::IdString ce
|
|||
cell->setPort(ID::Y, wire);
|
||||
}
|
||||
|
||||
if (cell_type == ID($priority))
|
||||
{
|
||||
int width = 1 + xorshift32(8 * bloat_factor);
|
||||
|
||||
wire = module->addWire(ID::A);
|
||||
wire->width = width;
|
||||
wire->port_input = true;
|
||||
cell->setPort(ID::A, wire);
|
||||
|
||||
wire = module->addWire(ID::Y);
|
||||
wire->width = width;
|
||||
wire->port_output = true;
|
||||
cell->setPort(ID::Y, wire);
|
||||
|
||||
RTLIL::SigSpec polarity;
|
||||
for (int i = 0; i < width; i++)
|
||||
polarity.append(xorshift32(2) ? State::S1 : State::S0);
|
||||
|
||||
cell->setParam(ID::POLARITY, polarity.as_const());
|
||||
}
|
||||
|
||||
if (cell_type == ID($fa))
|
||||
{
|
||||
int width = 1 + xorshift32(8 * bloat_factor);
|
||||
|
|
@ -1039,6 +1060,7 @@ struct TestCellPass : public Pass {
|
|||
cell_types[ID($mux)] = "*";
|
||||
cell_types[ID($bmux)] = "*";
|
||||
cell_types[ID($demux)] = "*";
|
||||
cell_types[ID($priority)] = "*";
|
||||
// $pmux doesn't work in sat, and is not supported with 'techmap -assert' or
|
||||
// '-simlib'
|
||||
if (nosat && techmap_cmd.compare("aigmap") == 0)
|
||||
|
|
|
|||
|
|
@ -3250,3 +3250,35 @@ parameter WIDTH = 0;
|
|||
inout [WIDTH-1:0] Y;
|
||||
|
||||
endmodule
|
||||
|
||||
// --------------------------------------------------------
|
||||
//-
|
||||
//- $priority (A, Y)
|
||||
//* group unary
|
||||
//-
|
||||
//- Priority operator. An output bit is set if the input bit at the same index is set and no lower index input bit is set.
|
||||
//-
|
||||
module \$priority (A, Y);
|
||||
parameter WIDTH = 0;
|
||||
parameter POLARITY = 0;
|
||||
input [WIDTH-1:0] A;
|
||||
output [WIDTH-1:0] Y;
|
||||
|
||||
wire [WIDTH-1:0] tmp;
|
||||
wire [WIDTH-1:0] A_active;
|
||||
wire [WIDTH-1:0] Y_active;
|
||||
assign A_active = A ^ ~POLARITY;
|
||||
assign Y = Y_active ^ ~POLARITY;
|
||||
genvar i;
|
||||
generate
|
||||
if (WIDTH > 0) begin
|
||||
assign tmp[0] = A_active[0];
|
||||
assign Y_active[0] = A_active[0];
|
||||
end
|
||||
for (i = 1; i < WIDTH; i = i + 1) begin
|
||||
assign Y_active[i] = tmp[i-1] ? 1'b0 : A_active[i];
|
||||
assign tmp[i] = tmp[i-1] | A_active[i];
|
||||
end
|
||||
endgenerate
|
||||
|
||||
endmodule
|
||||
|
|
|
|||
|
|
@ -679,3 +679,36 @@ parameter WIDTH = 0;
|
|||
inout [WIDTH-1:0] Y; // This cell is just a maker, so we leave Y undriven
|
||||
|
||||
endmodule
|
||||
|
||||
(* techmap_celltype = "$priority" *)
|
||||
module \$priority (A, Y);
|
||||
parameter WIDTH = 0;
|
||||
parameter POLARITY = 0;
|
||||
|
||||
(* force_downto *)
|
||||
input [WIDTH-1:0] A;
|
||||
(* force_downto *)
|
||||
output [WIDTH-1:0] Y;
|
||||
|
||||
(* force_downto *)
|
||||
wire [WIDTH-1:0] tmp;
|
||||
(* force_downto *)
|
||||
wire [WIDTH-1:0] A_active;
|
||||
(* force_downto *)
|
||||
wire [WIDTH-1:0] Y_active;
|
||||
assign A_active = A ^ ~POLARITY;
|
||||
assign Y = Y_active ^ ~POLARITY;
|
||||
|
||||
genvar i;
|
||||
generate
|
||||
if (WIDTH > 0) begin
|
||||
assign tmp[0] = A_active[0];
|
||||
assign Y_active[0] = A_active[0];
|
||||
end
|
||||
for (i = 1; i < WIDTH; i = i + 1) begin
|
||||
assign Y_active[i] = tmp[i-1] ? 1'b0 : A_active[i];
|
||||
assign tmp[i] = tmp[i-1] | A_active[i];
|
||||
end
|
||||
endgenerate
|
||||
|
||||
endmodule
|
||||
|
|
|
|||
5
tests/aiger/gold/_priority_00000.aag
Normal file
5
tests/aiger/gold/_priority_00000.aag
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
aag 1 1 0 1 0
|
||||
2
|
||||
2
|
||||
c
|
||||
Generated by Yosys
|
||||
|
|
@ -1,7 +1,12 @@
|
|||
aag 1 1 0 3 0
|
||||
2
|
||||
aag 5 3 0 4 2
|
||||
2
|
||||
4
|
||||
6
|
||||
10
|
||||
0
|
||||
0
|
||||
0
|
||||
8 4 2
|
||||
10 8 6
|
||||
c
|
||||
Generated by Yosys
|
||||
|
|
|
|||
|
|
@ -1,13 +1,9 @@
|
|||
aag 7 4 0 3 3
|
||||
aag 5 3 0 1 2
|
||||
2
|
||||
4
|
||||
6
|
||||
8
|
||||
15
|
||||
0
|
||||
0
|
||||
10 5 3
|
||||
12 10 7
|
||||
14 12 9
|
||||
11
|
||||
8 5 3
|
||||
10 8 7
|
||||
c
|
||||
Generated by Yosys
|
||||
|
|
|
|||
|
|
@ -1,7 +1,10 @@
|
|||
aag 3 2 0 1 1
|
||||
aag 1 1 0 6 0
|
||||
2
|
||||
4
|
||||
7
|
||||
6 5 3
|
||||
2
|
||||
0
|
||||
0
|
||||
0
|
||||
0
|
||||
0
|
||||
c
|
||||
Generated by Yosys
|
||||
|
|
|
|||
|
|
@ -1,30 +1,10 @@
|
|||
aag 25 6 0 2 19
|
||||
aag 5 2 0 2 3
|
||||
2
|
||||
4
|
||||
6
|
||||
8
|
||||
10
|
||||
12
|
||||
51
|
||||
11
|
||||
0
|
||||
14 4 2
|
||||
16 5 3
|
||||
18 17 15
|
||||
20 18 6
|
||||
22 17 15
|
||||
24 23 7
|
||||
26 25 21
|
||||
28 26 8
|
||||
30 25 21
|
||||
32 31 9
|
||||
34 33 29
|
||||
36 34 10
|
||||
38 33 29
|
||||
40 39 11
|
||||
42 41 37
|
||||
44 42 12
|
||||
46 41 37
|
||||
48 47 13
|
||||
50 49 45
|
||||
6 4 2
|
||||
8 5 3
|
||||
10 9 7
|
||||
c
|
||||
Generated by Yosys
|
||||
|
|
|
|||
|
|
@ -1,9 +1,7 @@
|
|||
aag 5 2 0 1 3
|
||||
aag 1 1 0 3 0
|
||||
2
|
||||
4
|
||||
10
|
||||
6 4 2
|
||||
8 5 3
|
||||
10 9 7
|
||||
2
|
||||
0
|
||||
0
|
||||
c
|
||||
Generated by Yosys
|
||||
|
|
|
|||
|
|
@ -1,20 +1,35 @@
|
|||
aag 16 13 0 1 3
|
||||
aag 29 6 0 3 23
|
||||
2
|
||||
4
|
||||
6
|
||||
8
|
||||
10
|
||||
12
|
||||
14
|
||||
16
|
||||
18
|
||||
20
|
||||
22
|
||||
24
|
||||
26
|
||||
33
|
||||
28 17 2
|
||||
30 16 3
|
||||
32 31 29
|
||||
19
|
||||
38
|
||||
58
|
||||
14 7 2
|
||||
16 6 3
|
||||
18 17 15
|
||||
20 6 3
|
||||
22 20 15
|
||||
24 9 4
|
||||
26 8 5
|
||||
28 27 25
|
||||
30 28 23
|
||||
32 27 25
|
||||
34 20 15
|
||||
36 34 33
|
||||
38 37 31
|
||||
40 27 23
|
||||
42 41 25
|
||||
44 11 4
|
||||
46 10 5
|
||||
48 47 45
|
||||
50 48 43
|
||||
52 47 45
|
||||
54 41 25
|
||||
56 54 53
|
||||
58 57 51
|
||||
c
|
||||
Generated by Yosys
|
||||
|
|
|
|||
|
|
@ -1,12 +1,16 @@
|
|||
aag 10 4 0 4 6
|
||||
aag 10 4 0 8 6
|
||||
2
|
||||
4
|
||||
6
|
||||
8
|
||||
15
|
||||
21
|
||||
21
|
||||
21
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
10 6 2
|
||||
12 7 3
|
||||
14 13 11
|
||||
|
|
|
|||
|
|
@ -1,12 +1,51 @@
|
|||
aag 8 5 0 1 3
|
||||
aag 40 16 0 8 24
|
||||
2
|
||||
4
|
||||
6
|
||||
8
|
||||
10
|
||||
12
|
||||
14
|
||||
16
|
||||
12 8 2
|
||||
14 9 3
|
||||
16 15 13
|
||||
18
|
||||
20
|
||||
22
|
||||
24
|
||||
26
|
||||
28
|
||||
30
|
||||
32
|
||||
38
|
||||
44
|
||||
50
|
||||
56
|
||||
62
|
||||
68
|
||||
74
|
||||
80
|
||||
34 18 2
|
||||
36 19 3
|
||||
38 37 35
|
||||
40 20 4
|
||||
42 21 5
|
||||
44 43 41
|
||||
46 22 6
|
||||
48 23 7
|
||||
50 49 47
|
||||
52 24 8
|
||||
54 25 9
|
||||
56 55 53
|
||||
58 26 10
|
||||
60 27 11
|
||||
62 61 59
|
||||
64 28 12
|
||||
66 29 13
|
||||
68 67 65
|
||||
70 30 14
|
||||
72 31 15
|
||||
74 73 71
|
||||
76 32 16
|
||||
78 33 17
|
||||
80 79 77
|
||||
c
|
||||
Generated by Yosys
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
read_verilog -icells <<EOT
|
||||
module top(input clk, d, s, r, output reg [17:0] q);
|
||||
read_verilog -formal -icells <<EOT
|
||||
module top(input clk, d, s, r, output reg [34:0] q);
|
||||
always @(posedge clk or posedge s) if ( s) q[ 0] <= 1'b1; else q[ 0] <= d;
|
||||
always @(posedge clk or negedge s) if (!s) q[ 1] <= 1'b1; else q[ 1] <= d;
|
||||
always @(posedge clk or posedge r) if ( r) q[ 2] <= 1'b0; else q[ 2] <= d;
|
||||
|
|
@ -9,30 +9,41 @@ always @(negedge clk or negedge s) if (!s) q[ 5] <= 1'b1; else q[ 5] <= d;
|
|||
always @(negedge clk or posedge r) if ( r) q[ 6] <= 1'b0; else q[ 6] <= d;
|
||||
always @(negedge clk or negedge r) if (!r) q[ 7] <= 1'b0; else q[ 7] <= d;
|
||||
|
||||
// Seems like proc_dlatch always sets {SET,CLR}_POLARITY to true
|
||||
always @(posedge clk or posedge s or posedge r) if ( r) q[ 8] <= 1'b0; else if ( s) q[ 8] <= 1'b1; else q[ 8] <= d;
|
||||
//always @(posedge clk or posedge s or negedge r) if (!r) q[ 9] <= 1'b0; else if ( s) q[ 9] <= 1'b1; else q[ 9] <= d;
|
||||
//always @(posedge clk or negedge s or posedge r) if ( r) q[10] <= 1'b0; else if (!s) q[10] <= 1'b1; else q[10] <= d;
|
||||
//always @(posedge clk or negedge s or negedge r) if (!r) q[11] <= 1'b0; else if (!s) q[11] <= 1'b1; else q[11] <= d;
|
||||
$dffsr #(.CLK_POLARITY(1'h1), .CLR_POLARITY(1'h0), .SET_POLARITY(1'h1), .WIDTH(32'd1)) ppn (.CLK(clk), .CLR(r), .D(d), .Q(q[ 9]), .SET(s));
|
||||
$dffsr #(.CLK_POLARITY(1'h1), .CLR_POLARITY(1'h1), .SET_POLARITY(1'h0), .WIDTH(32'd1)) pnp (.CLK(clk), .CLR(r), .D(d), .Q(q[10]), .SET(s));
|
||||
$dffsr #(.CLK_POLARITY(1'h1), .CLR_POLARITY(1'h0), .SET_POLARITY(1'h0), .WIDTH(32'd1)) pnn (.CLK(clk), .CLR(r), .D(d), .Q(q[11]), .SET(s));
|
||||
always @(posedge clk or posedge s or negedge r) if (!r) q[ 9] <= 1'b0; else if ( s) q[ 9] <= 1'b1; else q[ 9] <= d;
|
||||
always @(posedge clk or negedge s or posedge r) if ( r) q[10] <= 1'b0; else if (!s) q[10] <= 1'b1; else q[10] <= d;
|
||||
always @(posedge clk or negedge s or negedge r) if (!r) q[11] <= 1'b0; else if (!s) q[11] <= 1'b1; else q[11] <= d;
|
||||
$dffsr #(.CLK_POLARITY(1'h1), .SET_POLARITY(1'h0), .CLR_POLARITY(1'h0), .WIDTH(32'd1)) pnn (.CLK(clk), .CLR(r), .D(d), .Q(q[12]), .SET(s));
|
||||
$dffsr #(.CLK_POLARITY(1'h1), .SET_POLARITY(1'h0), .CLR_POLARITY(1'h1), .WIDTH(32'd1)) pnp (.CLK(clk), .CLR(r), .D(d), .Q(q[13]), .SET(s));
|
||||
$dffsr #(.CLK_POLARITY(1'h1), .SET_POLARITY(1'h1), .CLR_POLARITY(1'h0), .WIDTH(32'd1)) ppn (.CLK(clk), .CLR(r), .D(d), .Q(q[14]), .SET(s));
|
||||
$dffsr #(.CLK_POLARITY(1'h1), .SET_POLARITY(1'h1), .CLR_POLARITY(1'h1), .WIDTH(32'd1)) ppp (.CLK(clk), .CLR(r), .D(d), .Q(q[15]), .SET(s));
|
||||
|
||||
always @(negedge clk or posedge s or posedge r) if ( r) q[12] <= 1'b0; else if ( s) q[12] <= 1'b1; else q[12] <= d;
|
||||
//always @(negedge clk or posedge s or negedge r) if (!r) q[13] <= 1'b0; else if ( s) q[13] <= 1'b1; else q[13] <= d;
|
||||
//always @(negedge clk or negedge s or posedge r) if ( r) q[14] <= 1'b0; else if (!s) q[14] <= 1'b1; else q[14] <= d;
|
||||
//always @(negedge clk or negedge s or negedge r) if (!r) q[15] <= 1'b0; else if (!s) q[15] <= 1'b1; else q[15] <= d;
|
||||
$dffsr #(.CLK_POLARITY(1'h0), .CLR_POLARITY(1'h0), .SET_POLARITY(1'h1), .WIDTH(32'd1)) npn (.CLK(clk), .CLR(r), .D(d), .Q(q[13]), .SET(s));
|
||||
$dffsr #(.CLK_POLARITY(1'h0), .CLR_POLARITY(1'h1), .SET_POLARITY(1'h0), .WIDTH(32'd1)) nnp (.CLK(clk), .CLR(r), .D(d), .Q(q[14]), .SET(s));
|
||||
$dffsr #(.CLK_POLARITY(1'h0), .CLR_POLARITY(1'h0), .SET_POLARITY(1'h0), .WIDTH(32'd1)) nnn (.CLK(clk), .CLR(r), .D(d), .Q(q[15]), .SET(s));
|
||||
always @(negedge clk or posedge s or posedge r) if ( r) q[16] <= 1'b0; else if ( s) q[16] <= 1'b1; else q[16] <= d;
|
||||
always @(negedge clk or posedge s or negedge r) if (!r) q[17] <= 1'b0; else if ( s) q[17] <= 1'b1; else q[17] <= d;
|
||||
always @(negedge clk or negedge s or posedge r) if ( r) q[18] <= 1'b0; else if (!s) q[18] <= 1'b1; else q[18] <= d;
|
||||
always @(negedge clk or negedge s or negedge r) if (!r) q[19] <= 1'b0; else if (!s) q[19] <= 1'b1; else q[19] <= d;
|
||||
$dffsr #(.CLK_POLARITY(1'h0), .SET_POLARITY(1'h0), .CLR_POLARITY(1'h0), .WIDTH(32'd1)) nnn (.CLK(clk), .CLR(r), .D(d), .Q(q[20]), .SET(s));
|
||||
$dffsr #(.CLK_POLARITY(1'h0), .SET_POLARITY(1'h0), .CLR_POLARITY(1'h1), .WIDTH(32'd1)) nnp (.CLK(clk), .CLR(r), .D(d), .Q(q[21]), .SET(s));
|
||||
$dffsr #(.CLK_POLARITY(1'h0), .SET_POLARITY(1'h1), .CLR_POLARITY(1'h0), .WIDTH(32'd1)) npn (.CLK(clk), .CLR(r), .D(d), .Q(q[22]), .SET(s));
|
||||
$dffsr #(.CLK_POLARITY(1'h0), .SET_POLARITY(1'h1), .CLR_POLARITY(1'h1), .WIDTH(32'd1)) npp (.CLK(clk), .CLR(r), .D(d), .Q(q[23]), .SET(s));
|
||||
|
||||
always @(posedge clk) q[16] <= d;
|
||||
always @(negedge clk) q[17] <= d;
|
||||
always @(posedge clk or posedge r or posedge s) if ( s) q[24] <= 1'b1; else if ( r) q[24] <= 1'b0; else q[24] <= d;
|
||||
always @(posedge clk or posedge r or negedge s) if (!s) q[25] <= 1'b1; else if ( r) q[25] <= 1'b0; else q[25] <= d;
|
||||
always @(posedge clk or negedge r or posedge s) if ( s) q[26] <= 1'b1; else if (!r) q[26] <= 1'b0; else q[26] <= d;
|
||||
always @(posedge clk or negedge r or negedge s) if (!s) q[27] <= 1'b1; else if (!r) q[27] <= 1'b0; else q[27] <= d;
|
||||
|
||||
always @(negedge clk or posedge r or posedge s) if ( s) q[28] <= 1'b1; else if ( r) q[28] <= 1'b0; else q[28] <= d;
|
||||
always @(negedge clk or posedge r or negedge s) if (!s) q[29] <= 1'b1; else if ( r) q[29] <= 1'b0; else q[29] <= d;
|
||||
always @(negedge clk or negedge r or posedge s) if ( s) q[30] <= 1'b1; else if (!r) q[30] <= 1'b0; else q[30] <= d;
|
||||
always @(negedge clk or negedge r or negedge s) if (!s) q[31] <= 1'b1; else if (!r) q[31] <= 1'b0; else q[31] <= d;
|
||||
|
||||
always @(posedge clk) q[32] <= d;
|
||||
always @(negedge clk) q[33] <= d;
|
||||
endmodule
|
||||
EOT
|
||||
proc
|
||||
select -assert-count 8 t:$adff
|
||||
select -assert-count 8 t:$dffsr
|
||||
select -assert-count 24 t:$dffsr
|
||||
select -assert-count 2 t:$dff
|
||||
design -save gold
|
||||
|
||||
|
|
@ -46,14 +57,14 @@ select -assert-count 1 t:$_DFF_PN1_
|
|||
select -assert-count 1 t:$_DFF_PP0_
|
||||
select -assert-count 1 t:$_DFF_PP1_
|
||||
stat
|
||||
select -assert-count 1 t:$_DFFSR_NNN_
|
||||
select -assert-count 1 t:$_DFFSR_NNP_
|
||||
select -assert-count 1 t:$_DFFSR_NPN_
|
||||
select -assert-count 1 t:$_DFFSR_NPP_
|
||||
select -assert-count 1 t:$_DFFSR_PNN_
|
||||
select -assert-count 1 t:$_DFFSR_PNP_
|
||||
select -assert-count 1 t:$_DFFSR_PPN_
|
||||
select -assert-count 1 t:$_DFFSR_PPP_
|
||||
select -assert-count 3 t:$_DFFSR_NNN_
|
||||
select -assert-count 3 t:$_DFFSR_NNP_
|
||||
select -assert-count 3 t:$_DFFSR_NPN_
|
||||
select -assert-count 3 t:$_DFFSR_NPP_
|
||||
select -assert-count 3 t:$_DFFSR_PNN_
|
||||
select -assert-count 3 t:$_DFFSR_PNP_
|
||||
select -assert-count 3 t:$_DFFSR_PPN_
|
||||
select -assert-count 3 t:$_DFFSR_PPP_
|
||||
select -assert-count 1 t:$_DFF_N_
|
||||
select -assert-count 1 t:$_DFF_P_
|
||||
design -stash gate
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue