mirror of
https://github.com/YosysHQ/yosys
synced 2025-04-13 04:28:18 +00:00
Merge pull request #1851 from YosysHQ/claire/bitselwrite
Improved rewrite code for writing to bit slice
This commit is contained in:
commit
9e1afde7a0
|
@ -218,6 +218,7 @@ AstNode::AstNode(AstNodeType type, AstNode *child1, AstNode *child2, AstNode *ch
|
||||||
realvalue = 0;
|
realvalue = 0;
|
||||||
id2ast = NULL;
|
id2ast = NULL;
|
||||||
basic_prep = false;
|
basic_prep = false;
|
||||||
|
lookahead = false;
|
||||||
|
|
||||||
if (child1)
|
if (child1)
|
||||||
children.push_back(child1);
|
children.push_back(child1);
|
||||||
|
@ -310,6 +311,10 @@ void AstNode::dumpAst(FILE *f, std::string indent) const
|
||||||
fprintf(f, " reg");
|
fprintf(f, " reg");
|
||||||
if (is_signed)
|
if (is_signed)
|
||||||
fprintf(f, " signed");
|
fprintf(f, " signed");
|
||||||
|
if (basic_prep)
|
||||||
|
fprintf(f, " basic_prep");
|
||||||
|
if (lookahead)
|
||||||
|
fprintf(f, " lookahead");
|
||||||
if (port_id > 0)
|
if (port_id > 0)
|
||||||
fprintf(f, " port=%d", port_id);
|
fprintf(f, " port=%d", port_id);
|
||||||
if (range_valid || range_left != -1 || range_right != 0)
|
if (range_valid || range_left != -1 || range_right != 0)
|
||||||
|
|
|
@ -202,6 +202,9 @@ namespace AST
|
||||||
// this is used by simplify to detect if basic analysis has been performed already on the node
|
// this is used by simplify to detect if basic analysis has been performed already on the node
|
||||||
bool basic_prep;
|
bool basic_prep;
|
||||||
|
|
||||||
|
// this is used for ID references in RHS expressions that should use the "new" value for non-blocking assignments
|
||||||
|
bool lookahead;
|
||||||
|
|
||||||
// this is the original sourcecode location that resulted in this AST node
|
// this is the original sourcecode location that resulted in this AST node
|
||||||
// it is automatically set by the constructor using AST::current_filename and
|
// it is automatically set by the constructor using AST::current_filename and
|
||||||
// the AST::get_line_num() callback function.
|
// the AST::get_line_num() callback function.
|
||||||
|
@ -352,6 +355,7 @@ namespace AST_INTERNAL
|
||||||
extern AST::AstNode *current_always, *current_top_block, *current_block, *current_block_child;
|
extern AST::AstNode *current_always, *current_top_block, *current_block, *current_block_child;
|
||||||
extern AST::AstModule *current_module;
|
extern AST::AstModule *current_module;
|
||||||
extern bool current_always_clocked;
|
extern bool current_always_clocked;
|
||||||
|
struct LookaheadRewriter;
|
||||||
struct ProcessGenerator;
|
struct ProcessGenerator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -157,6 +157,126 @@ static RTLIL::SigSpec mux2rtlil(AstNode *that, const RTLIL::SigSpec &cond, const
|
||||||
return wire;
|
return wire;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// helper class for rewriting simple lookahead references in AST always blocks
|
||||||
|
struct AST_INTERNAL::LookaheadRewriter
|
||||||
|
{
|
||||||
|
dict<IdString, pair<AstNode*, AstNode*>> lookaheadids;
|
||||||
|
|
||||||
|
void collect_lookaheadids(AstNode *node)
|
||||||
|
{
|
||||||
|
if (node->lookahead) {
|
||||||
|
log_assert(node->type == AST_IDENTIFIER);
|
||||||
|
if (!lookaheadids.count(node->str)) {
|
||||||
|
AstNode *wire = new AstNode(AST_WIRE);
|
||||||
|
for (auto c : node->id2ast->children)
|
||||||
|
wire->children.push_back(c->clone());
|
||||||
|
wire->str = stringf("$lookahead%s$%d", node->str.c_str(), autoidx++);
|
||||||
|
wire->attributes["\\nosync"] = AstNode::mkconst_int(1, false);
|
||||||
|
wire->is_logic = true;
|
||||||
|
while (wire->simplify(true, false, false, 1, -1, false, false)) { }
|
||||||
|
current_ast_mod->children.push_back(wire);
|
||||||
|
lookaheadids[node->str] = make_pair(node->id2ast, wire);
|
||||||
|
wire->genRTLIL();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto child : node->children)
|
||||||
|
collect_lookaheadids(child);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool has_lookaheadids(AstNode *node)
|
||||||
|
{
|
||||||
|
if (node->type == AST_IDENTIFIER && lookaheadids.count(node->str) != 0)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
for (auto child : node->children)
|
||||||
|
if (has_lookaheadids(child))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool has_nonlookaheadids(AstNode *node)
|
||||||
|
{
|
||||||
|
if (node->type == AST_IDENTIFIER && lookaheadids.count(node->str) == 0)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
for (auto child : node->children)
|
||||||
|
if (has_nonlookaheadids(child))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rewrite_lookaheadids(AstNode *node, bool lhs = false)
|
||||||
|
{
|
||||||
|
if (node->type == AST_ASSIGN_LE)
|
||||||
|
{
|
||||||
|
if (has_lookaheadids(node->children[0]))
|
||||||
|
{
|
||||||
|
if (has_nonlookaheadids(node->children[0]))
|
||||||
|
log_error("incompatible mix of lookahead and non-lookahead IDs in LHS expression.\n");
|
||||||
|
|
||||||
|
rewrite_lookaheadids(node->children[0], true);
|
||||||
|
node->type = AST_ASSIGN_EQ;
|
||||||
|
}
|
||||||
|
|
||||||
|
rewrite_lookaheadids(node->children[1], lhs);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node->type == AST_IDENTIFIER && (node->lookahead || lhs)) {
|
||||||
|
AstNode *newwire = lookaheadids.at(node->str).second;
|
||||||
|
node->str = newwire->str;
|
||||||
|
node->id2ast = newwire;
|
||||||
|
lhs = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto child : node->children)
|
||||||
|
rewrite_lookaheadids(child, lhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
LookaheadRewriter(AstNode *top)
|
||||||
|
{
|
||||||
|
// top->dumpAst(NULL, "REWRITE-BEFORE> ");
|
||||||
|
// top->dumpVlog(NULL, "REWRITE-BEFORE> ");
|
||||||
|
|
||||||
|
AstNode *block = nullptr;
|
||||||
|
|
||||||
|
for (auto c : top->children)
|
||||||
|
if (c->type == AST_BLOCK) {
|
||||||
|
log_assert(block == nullptr);
|
||||||
|
block = c;
|
||||||
|
}
|
||||||
|
log_assert(block != nullptr);
|
||||||
|
|
||||||
|
collect_lookaheadids(block);
|
||||||
|
rewrite_lookaheadids(block);
|
||||||
|
|
||||||
|
for (auto it : lookaheadids)
|
||||||
|
{
|
||||||
|
AstNode *ref_orig = new AstNode(AST_IDENTIFIER);
|
||||||
|
ref_orig->str = it.second.first->str;
|
||||||
|
ref_orig->id2ast = it.second.first;
|
||||||
|
ref_orig->was_checked = true;
|
||||||
|
|
||||||
|
AstNode *ref_temp = new AstNode(AST_IDENTIFIER);
|
||||||
|
ref_temp->str = it.second.second->str;
|
||||||
|
ref_temp->id2ast = it.second.second;
|
||||||
|
ref_temp->was_checked = true;
|
||||||
|
|
||||||
|
AstNode *init_assign = new AstNode(AST_ASSIGN_EQ, ref_temp->clone(), ref_orig->clone());
|
||||||
|
AstNode *final_assign = new AstNode(AST_ASSIGN_LE, ref_orig, ref_temp);
|
||||||
|
|
||||||
|
block->children.insert(block->children.begin(), init_assign);
|
||||||
|
block->children.push_back(final_assign);
|
||||||
|
}
|
||||||
|
|
||||||
|
// top->dumpAst(NULL, "REWRITE-AFTER> ");
|
||||||
|
// top->dumpVlog(NULL, "REWRITE-AFTER> ");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// helper class for converting AST always nodes to RTLIL processes
|
// helper class for converting AST always nodes to RTLIL processes
|
||||||
struct AST_INTERNAL::ProcessGenerator
|
struct AST_INTERNAL::ProcessGenerator
|
||||||
{
|
{
|
||||||
|
@ -191,6 +311,9 @@ struct AST_INTERNAL::ProcessGenerator
|
||||||
|
|
||||||
ProcessGenerator(AstNode *always, RTLIL::SigSpec initSyncSignalsArg = RTLIL::SigSpec()) : always(always), initSyncSignals(initSyncSignalsArg)
|
ProcessGenerator(AstNode *always, RTLIL::SigSpec initSyncSignalsArg = RTLIL::SigSpec()) : always(always), initSyncSignals(initSyncSignalsArg)
|
||||||
{
|
{
|
||||||
|
// rewrite lookahead references
|
||||||
|
LookaheadRewriter la_rewriter(always);
|
||||||
|
|
||||||
// generate process and simple root case
|
// generate process and simple root case
|
||||||
proc = new RTLIL::Process;
|
proc = new RTLIL::Process;
|
||||||
proc->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", always->filename.c_str(), always->location.first_line, always->location.first_column, always->location.last_line, always->location.last_column);
|
proc->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", always->filename.c_str(), always->location.first_line, always->location.first_column, always->location.last_line, always->location.last_column);
|
||||||
|
@ -338,7 +461,7 @@ struct AST_INTERNAL::ProcessGenerator
|
||||||
return chunks;
|
return chunks;
|
||||||
}
|
}
|
||||||
|
|
||||||
// recursively traverse the AST an collect all assigned signals
|
// recursively traverse the AST and collect all assigned signals
|
||||||
void collect_lvalues(RTLIL::SigSpec ®, AstNode *ast, bool type_eq, bool type_le, bool run_sort_and_unify = true)
|
void collect_lvalues(RTLIL::SigSpec ®, AstNode *ast, bool type_eq, bool type_le, bool run_sort_and_unify = true)
|
||||||
{
|
{
|
||||||
switch (ast->type)
|
switch (ast->type)
|
||||||
|
@ -1010,7 +1133,9 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
|
||||||
int add_undef_bits_msb = 0;
|
int add_undef_bits_msb = 0;
|
||||||
int add_undef_bits_lsb = 0;
|
int add_undef_bits_lsb = 0;
|
||||||
|
|
||||||
if (id2ast && id2ast->type == AST_AUTOWIRE && current_module->wires_.count(str) == 0) {
|
log_assert(id2ast != nullptr);
|
||||||
|
|
||||||
|
if (id2ast->type == AST_AUTOWIRE && current_module->wires_.count(str) == 0) {
|
||||||
RTLIL::Wire *wire = current_module->addWire(str);
|
RTLIL::Wire *wire = current_module->addWire(str);
|
||||||
wire->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", filename.c_str(), location.first_line, location.first_column, location.last_line, location.last_column);
|
wire->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", filename.c_str(), location.first_line, location.first_column, location.last_line, location.last_column);
|
||||||
wire->name = str;
|
wire->name = str;
|
||||||
|
@ -1025,7 +1150,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
|
||||||
chunk = RTLIL::Const(id2ast->children[0]->bits);
|
chunk = RTLIL::Const(id2ast->children[0]->bits);
|
||||||
goto use_const_chunk;
|
goto use_const_chunk;
|
||||||
}
|
}
|
||||||
else if (id2ast && (id2ast->type == AST_WIRE || id2ast->type == AST_AUTOWIRE || id2ast->type == AST_MEMORY) && current_module->wires_.count(str) != 0) {
|
else if ((id2ast->type == AST_WIRE || id2ast->type == AST_AUTOWIRE || id2ast->type == AST_MEMORY) && current_module->wires_.count(str) != 0) {
|
||||||
RTLIL::Wire *current_wire = current_module->wire(str);
|
RTLIL::Wire *current_wire = current_module->wire(str);
|
||||||
if (current_wire->get_bool_attribute(ID::is_interface))
|
if (current_wire->get_bool_attribute(ID::is_interface))
|
||||||
is_interface = true;
|
is_interface = true;
|
||||||
|
|
|
@ -1754,8 +1754,10 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
|
||||||
}
|
}
|
||||||
|
|
||||||
// replace dynamic ranges in left-hand side expressions (e.g. "foo[bar] <= 1'b1;") with
|
// replace dynamic ranges in left-hand side expressions (e.g. "foo[bar] <= 1'b1;") with
|
||||||
// a big case block that selects the correct single-bit assignment.
|
// either a big case block that selects the correct single-bit assignment, or mask and
|
||||||
if (type == AST_ASSIGN_EQ || type == AST_ASSIGN_LE) {
|
// shift operations.
|
||||||
|
if (type == AST_ASSIGN_EQ || type == AST_ASSIGN_LE)
|
||||||
|
{
|
||||||
if (children[0]->type != AST_IDENTIFIER || children[0]->children.size() == 0)
|
if (children[0]->type != AST_IDENTIFIER || children[0]->children.size() == 0)
|
||||||
goto skip_dynamic_range_lvalue_expansion;
|
goto skip_dynamic_range_lvalue_expansion;
|
||||||
if (children[0]->children[0]->range_valid || did_something)
|
if (children[0]->children[0]->range_valid || did_something)
|
||||||
|
@ -1764,10 +1766,13 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
|
||||||
goto skip_dynamic_range_lvalue_expansion;
|
goto skip_dynamic_range_lvalue_expansion;
|
||||||
if (!children[0]->id2ast->range_valid)
|
if (!children[0]->id2ast->range_valid)
|
||||||
goto skip_dynamic_range_lvalue_expansion;
|
goto skip_dynamic_range_lvalue_expansion;
|
||||||
|
|
||||||
int source_width = children[0]->id2ast->range_left - children[0]->id2ast->range_right + 1;
|
int source_width = children[0]->id2ast->range_left - children[0]->id2ast->range_right + 1;
|
||||||
int result_width = 1;
|
int result_width = 1;
|
||||||
|
|
||||||
AstNode *shift_expr = NULL;
|
AstNode *shift_expr = NULL;
|
||||||
AstNode *range = children[0]->children[0];
|
AstNode *range = children[0]->children[0];
|
||||||
|
|
||||||
if (range->children.size() == 1) {
|
if (range->children.size() == 1) {
|
||||||
shift_expr = range->children[0]->clone();
|
shift_expr = range->children[0]->clone();
|
||||||
} else {
|
} else {
|
||||||
|
@ -1780,19 +1785,72 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
|
||||||
log_file_error(filename, location.first_line, "Unsupported expression on dynamic range select on signal `%s'!\n", str.c_str());
|
log_file_error(filename, location.first_line, "Unsupported expression on dynamic range select on signal `%s'!\n", str.c_str());
|
||||||
result_width = abs(int(left_at_zero_ast->integer - right_at_zero_ast->integer)) + 1;
|
result_width = abs(int(left_at_zero_ast->integer - right_at_zero_ast->integer)) + 1;
|
||||||
}
|
}
|
||||||
did_something = true;
|
|
||||||
newNode = new AstNode(AST_CASE, shift_expr);
|
if (0)
|
||||||
for (int i = 0; i < source_width; i++) {
|
{
|
||||||
int start_bit = children[0]->id2ast->range_right + i;
|
// big case block
|
||||||
AstNode *cond = new AstNode(AST_COND, mkconst_int(start_bit, true));
|
|
||||||
|
did_something = true;
|
||||||
|
newNode = new AstNode(AST_CASE, shift_expr);
|
||||||
|
for (int i = 0; i < source_width; i++) {
|
||||||
|
int start_bit = children[0]->id2ast->range_right + i;
|
||||||
|
AstNode *cond = new AstNode(AST_COND, mkconst_int(start_bit, true));
|
||||||
|
AstNode *lvalue = children[0]->clone();
|
||||||
|
lvalue->delete_children();
|
||||||
|
int end_bit = std::min(start_bit+result_width,source_width) - 1;
|
||||||
|
lvalue->children.push_back(new AstNode(AST_RANGE,
|
||||||
|
mkconst_int(end_bit, true), mkconst_int(start_bit, true)));
|
||||||
|
cond->children.push_back(new AstNode(AST_BLOCK, new AstNode(type, lvalue, children[1]->clone())));
|
||||||
|
newNode->children.push_back(cond);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// mask and shift operations, disabled for now
|
||||||
|
|
||||||
|
AstNode *wire_mask = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(source_width-1, true), mkconst_int(0, true)));
|
||||||
|
wire_mask->str = stringf("$bitselwrite$mask$%s:%d$%d", filename.c_str(), location.first_line, autoidx++);
|
||||||
|
wire_mask->attributes["\\nosync"] = AstNode::mkconst_int(1, false);
|
||||||
|
wire_mask->is_logic = true;
|
||||||
|
while (wire_mask->simplify(true, false, false, 1, -1, false, false)) { }
|
||||||
|
current_ast_mod->children.push_back(wire_mask);
|
||||||
|
|
||||||
|
AstNode *wire_data = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(source_width-1, true), mkconst_int(0, true)));
|
||||||
|
wire_data->str = stringf("$bitselwrite$data$%s:%d$%d", filename.c_str(), location.first_line, autoidx++);
|
||||||
|
wire_data->attributes["\\nosync"] = AstNode::mkconst_int(1, false);
|
||||||
|
wire_data->is_logic = true;
|
||||||
|
while (wire_data->simplify(true, false, false, 1, -1, false, false)) { }
|
||||||
|
current_ast_mod->children.push_back(wire_data);
|
||||||
|
|
||||||
|
did_something = true;
|
||||||
|
newNode = new AstNode(AST_BLOCK);
|
||||||
|
|
||||||
AstNode *lvalue = children[0]->clone();
|
AstNode *lvalue = children[0]->clone();
|
||||||
lvalue->delete_children();
|
lvalue->delete_children();
|
||||||
int end_bit = std::min(start_bit+result_width,source_width) - 1;
|
|
||||||
lvalue->children.push_back(new AstNode(AST_RANGE,
|
AstNode *ref_mask = new AstNode(AST_IDENTIFIER);
|
||||||
mkconst_int(end_bit, true), mkconst_int(start_bit, true)));
|
ref_mask->str = wire_mask->str;
|
||||||
cond->children.push_back(new AstNode(AST_BLOCK, new AstNode(type, lvalue, children[1]->clone())));
|
ref_mask->id2ast = wire_mask;
|
||||||
newNode->children.push_back(cond);
|
ref_mask->was_checked = true;
|
||||||
|
|
||||||
|
AstNode *ref_data = new AstNode(AST_IDENTIFIER);
|
||||||
|
ref_data->str = wire_data->str;
|
||||||
|
ref_data->id2ast = wire_data;
|
||||||
|
ref_data->was_checked = true;
|
||||||
|
|
||||||
|
AstNode *old_data = lvalue->clone();
|
||||||
|
if (type == AST_ASSIGN_LE)
|
||||||
|
old_data->lookahead = true;
|
||||||
|
|
||||||
|
AstNode *shamt = shift_expr;
|
||||||
|
|
||||||
|
newNode->children.push_back(new AstNode(AST_ASSIGN_EQ, ref_mask->clone(),
|
||||||
|
new AstNode(AST_SHIFT_LEFT, mkconst_bits(std::vector<RTLIL::State>(result_width, State::S1), false), shamt->clone())));
|
||||||
|
newNode->children.push_back(new AstNode(AST_ASSIGN_EQ, ref_data->clone(),
|
||||||
|
new AstNode(AST_SHIFT_LEFT, new AstNode(AST_BIT_AND, mkconst_bits(std::vector<RTLIL::State>(result_width, State::S1), false), children[1]->clone()), shamt)));
|
||||||
|
newNode->children.push_back(new AstNode(type, lvalue, new AstNode(AST_BIT_OR, new AstNode(AST_BIT_AND, old_data, new AstNode(AST_BIT_NOT, ref_mask)), ref_data)));
|
||||||
}
|
}
|
||||||
|
|
||||||
goto apply_newNode;
|
goto apply_newNode;
|
||||||
}
|
}
|
||||||
skip_dynamic_range_lvalue_expansion:;
|
skip_dynamic_range_lvalue_expansion:;
|
||||||
|
|
106
tests/various/dynamic_part_select.ys
Normal file
106
tests/various/dynamic_part_select.ys
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
### Original testcase ###
|
||||||
|
read_verilog ./dynamic_part_select/original.v
|
||||||
|
proc
|
||||||
|
rename -top gold
|
||||||
|
design -stash gold
|
||||||
|
|
||||||
|
read_verilog ./dynamic_part_select/original_gate.v
|
||||||
|
proc
|
||||||
|
rename -top gate
|
||||||
|
design -stash gate
|
||||||
|
|
||||||
|
design -copy-from gold -as gold gold
|
||||||
|
design -copy-from gate -as gate gate
|
||||||
|
|
||||||
|
miter -equiv -make_assert -make_outcmp -flatten gold gate equiv
|
||||||
|
sat -prove-asserts -seq 10 -show-public -verify -set-init-zero equiv
|
||||||
|
|
||||||
|
### Multiple blocking assingments ###
|
||||||
|
design -reset
|
||||||
|
read_verilog ./dynamic_part_select/multiple_blocking.v
|
||||||
|
proc
|
||||||
|
rename -top gold
|
||||||
|
design -stash gold
|
||||||
|
|
||||||
|
read_verilog ./dynamic_part_select/multiple_blocking_gate.v
|
||||||
|
proc
|
||||||
|
rename -top gate
|
||||||
|
design -stash gate
|
||||||
|
|
||||||
|
design -copy-from gold -as gold gold
|
||||||
|
design -copy-from gate -as gate gate
|
||||||
|
|
||||||
|
miter -equiv -make_assert -make_outcmp -flatten gold gate equiv
|
||||||
|
sat -prove-asserts -seq 10 -show-public -verify -set-init-zero equiv
|
||||||
|
|
||||||
|
### Non-blocking to the same output register ###
|
||||||
|
design -reset
|
||||||
|
read_verilog ./dynamic_part_select/nonblocking.v
|
||||||
|
proc
|
||||||
|
rename -top gold
|
||||||
|
design -stash gold
|
||||||
|
|
||||||
|
read_verilog ./dynamic_part_select/nonblocking_gate.v
|
||||||
|
proc
|
||||||
|
rename -top gate
|
||||||
|
design -stash gate
|
||||||
|
|
||||||
|
design -copy-from gold -as gold gold
|
||||||
|
design -copy-from gate -as gate gate
|
||||||
|
|
||||||
|
miter -equiv -make_assert -make_outcmp -flatten gold gate equiv
|
||||||
|
sat -prove-asserts -seq 10 -show-public -verify -set-init-zero equiv
|
||||||
|
|
||||||
|
### For-loop select, one dynamic input
|
||||||
|
design -reset
|
||||||
|
read_verilog ./dynamic_part_select/forloop_select.v
|
||||||
|
proc
|
||||||
|
rename -top gold
|
||||||
|
design -stash gold
|
||||||
|
|
||||||
|
read_verilog ./dynamic_part_select/forloop_select_gate.v
|
||||||
|
proc
|
||||||
|
rename -top gate
|
||||||
|
design -stash gate
|
||||||
|
|
||||||
|
design -copy-from gold -as gold gold
|
||||||
|
design -copy-from gate -as gate gate
|
||||||
|
|
||||||
|
miter -equiv -make_assert -make_outcmp -flatten gold gate equiv
|
||||||
|
sat -prove-asserts -seq 10 -show-public -verify -set-init-zero equiv
|
||||||
|
|
||||||
|
#### Double loop (part-select, reset) ###
|
||||||
|
design -reset
|
||||||
|
read_verilog ./dynamic_part_select/reset_test.v
|
||||||
|
proc
|
||||||
|
rename -top gold
|
||||||
|
design -stash gold
|
||||||
|
|
||||||
|
read_verilog ./dynamic_part_select/reset_test_gate.v
|
||||||
|
proc
|
||||||
|
rename -top gate
|
||||||
|
design -stash gate
|
||||||
|
|
||||||
|
design -copy-from gold -as gold gold
|
||||||
|
design -copy-from gate -as gate gate
|
||||||
|
|
||||||
|
miter -equiv -make_assert -make_outcmp -flatten gold gate equiv
|
||||||
|
sat -prove-asserts -seq 10 -show-public -verify -set-init-zero equiv
|
||||||
|
|
||||||
|
### Reversed part-select case ###
|
||||||
|
design -reset
|
||||||
|
read_verilog ./dynamic_part_select/reversed.v
|
||||||
|
proc
|
||||||
|
rename -top gold
|
||||||
|
design -stash gold
|
||||||
|
|
||||||
|
read_verilog ./dynamic_part_select/reversed_gate.v
|
||||||
|
proc
|
||||||
|
rename -top gate
|
||||||
|
design -stash gate
|
||||||
|
|
||||||
|
design -copy-from gold -as gold gold
|
||||||
|
design -copy-from gate -as gate gate
|
||||||
|
|
||||||
|
miter -equiv -make_assert -make_outcmp -flatten gold gate equiv
|
||||||
|
sat -prove-asserts -seq 10 -show-public -verify -set-init-zero equiv
|
19
tests/various/dynamic_part_select/forloop_select.v
Normal file
19
tests/various/dynamic_part_select/forloop_select.v
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
module forloop_select #(parameter WIDTH=16, SELW=4, CTRLW=$clog2(WIDTH), DINW=2**SELW)
|
||||||
|
(input clk,
|
||||||
|
input [CTRLW-1:0] ctrl,
|
||||||
|
input [DINW-1:0] din,
|
||||||
|
input en,
|
||||||
|
output reg [WIDTH-1:0] dout);
|
||||||
|
|
||||||
|
reg [SELW:0] sel;
|
||||||
|
localparam SLICE = WIDTH/(SELW**2);
|
||||||
|
|
||||||
|
always @(posedge clk)
|
||||||
|
begin
|
||||||
|
if (en) begin
|
||||||
|
for (sel = 0; sel <= 4'hf; sel=sel+1'b1)
|
||||||
|
dout[(ctrl*sel)+:SLICE] <= din;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
|
|
559
tests/various/dynamic_part_select/forloop_select_gate.v
Normal file
559
tests/various/dynamic_part_select/forloop_select_gate.v
Normal file
|
@ -0,0 +1,559 @@
|
||||||
|
module forloop_select_gate (clk, ctrl, din, en, dout);
|
||||||
|
input clk;
|
||||||
|
input [3:0] ctrl;
|
||||||
|
input [15:0] din;
|
||||||
|
input en;
|
||||||
|
output reg [15:0] dout;
|
||||||
|
reg [4:0] sel;
|
||||||
|
always @(posedge clk)
|
||||||
|
case (|(en))
|
||||||
|
1'b 1:
|
||||||
|
begin
|
||||||
|
case (({(ctrl)*(0)})+(0))
|
||||||
|
0:
|
||||||
|
dout[0:0] <= din;
|
||||||
|
1:
|
||||||
|
dout[1:1] <= din;
|
||||||
|
2:
|
||||||
|
dout[2:2] <= din;
|
||||||
|
3:
|
||||||
|
dout[3:3] <= din;
|
||||||
|
4:
|
||||||
|
dout[4:4] <= din;
|
||||||
|
5:
|
||||||
|
dout[5:5] <= din;
|
||||||
|
6:
|
||||||
|
dout[6:6] <= din;
|
||||||
|
7:
|
||||||
|
dout[7:7] <= din;
|
||||||
|
8:
|
||||||
|
dout[8:8] <= din;
|
||||||
|
9:
|
||||||
|
dout[9:9] <= din;
|
||||||
|
10:
|
||||||
|
dout[10:10] <= din;
|
||||||
|
11:
|
||||||
|
dout[11:11] <= din;
|
||||||
|
12:
|
||||||
|
dout[12:12] <= din;
|
||||||
|
13:
|
||||||
|
dout[13:13] <= din;
|
||||||
|
14:
|
||||||
|
dout[14:14] <= din;
|
||||||
|
15:
|
||||||
|
dout[15:15] <= din;
|
||||||
|
endcase
|
||||||
|
case (({(ctrl)*(5'b 00001)})+(0))
|
||||||
|
0:
|
||||||
|
dout[0:0] <= din;
|
||||||
|
1:
|
||||||
|
dout[1:1] <= din;
|
||||||
|
2:
|
||||||
|
dout[2:2] <= din;
|
||||||
|
3:
|
||||||
|
dout[3:3] <= din;
|
||||||
|
4:
|
||||||
|
dout[4:4] <= din;
|
||||||
|
5:
|
||||||
|
dout[5:5] <= din;
|
||||||
|
6:
|
||||||
|
dout[6:6] <= din;
|
||||||
|
7:
|
||||||
|
dout[7:7] <= din;
|
||||||
|
8:
|
||||||
|
dout[8:8] <= din;
|
||||||
|
9:
|
||||||
|
dout[9:9] <= din;
|
||||||
|
10:
|
||||||
|
dout[10:10] <= din;
|
||||||
|
11:
|
||||||
|
dout[11:11] <= din;
|
||||||
|
12:
|
||||||
|
dout[12:12] <= din;
|
||||||
|
13:
|
||||||
|
dout[13:13] <= din;
|
||||||
|
14:
|
||||||
|
dout[14:14] <= din;
|
||||||
|
15:
|
||||||
|
dout[15:15] <= din;
|
||||||
|
endcase
|
||||||
|
case (({(ctrl)*(5'b 00010)})+(0))
|
||||||
|
0:
|
||||||
|
dout[0:0] <= din;
|
||||||
|
1:
|
||||||
|
dout[1:1] <= din;
|
||||||
|
2:
|
||||||
|
dout[2:2] <= din;
|
||||||
|
3:
|
||||||
|
dout[3:3] <= din;
|
||||||
|
4:
|
||||||
|
dout[4:4] <= din;
|
||||||
|
5:
|
||||||
|
dout[5:5] <= din;
|
||||||
|
6:
|
||||||
|
dout[6:6] <= din;
|
||||||
|
7:
|
||||||
|
dout[7:7] <= din;
|
||||||
|
8:
|
||||||
|
dout[8:8] <= din;
|
||||||
|
9:
|
||||||
|
dout[9:9] <= din;
|
||||||
|
10:
|
||||||
|
dout[10:10] <= din;
|
||||||
|
11:
|
||||||
|
dout[11:11] <= din;
|
||||||
|
12:
|
||||||
|
dout[12:12] <= din;
|
||||||
|
13:
|
||||||
|
dout[13:13] <= din;
|
||||||
|
14:
|
||||||
|
dout[14:14] <= din;
|
||||||
|
15:
|
||||||
|
dout[15:15] <= din;
|
||||||
|
endcase
|
||||||
|
case (({(ctrl)*(5'b 00011)})+(0))
|
||||||
|
0:
|
||||||
|
dout[0:0] <= din;
|
||||||
|
1:
|
||||||
|
dout[1:1] <= din;
|
||||||
|
2:
|
||||||
|
dout[2:2] <= din;
|
||||||
|
3:
|
||||||
|
dout[3:3] <= din;
|
||||||
|
4:
|
||||||
|
dout[4:4] <= din;
|
||||||
|
5:
|
||||||
|
dout[5:5] <= din;
|
||||||
|
6:
|
||||||
|
dout[6:6] <= din;
|
||||||
|
7:
|
||||||
|
dout[7:7] <= din;
|
||||||
|
8:
|
||||||
|
dout[8:8] <= din;
|
||||||
|
9:
|
||||||
|
dout[9:9] <= din;
|
||||||
|
10:
|
||||||
|
dout[10:10] <= din;
|
||||||
|
11:
|
||||||
|
dout[11:11] <= din;
|
||||||
|
12:
|
||||||
|
dout[12:12] <= din;
|
||||||
|
13:
|
||||||
|
dout[13:13] <= din;
|
||||||
|
14:
|
||||||
|
dout[14:14] <= din;
|
||||||
|
15:
|
||||||
|
dout[15:15] <= din;
|
||||||
|
endcase
|
||||||
|
case (({(ctrl)*(5'b 00100)})+(0))
|
||||||
|
0:
|
||||||
|
dout[0:0] <= din;
|
||||||
|
1:
|
||||||
|
dout[1:1] <= din;
|
||||||
|
2:
|
||||||
|
dout[2:2] <= din;
|
||||||
|
3:
|
||||||
|
dout[3:3] <= din;
|
||||||
|
4:
|
||||||
|
dout[4:4] <= din;
|
||||||
|
5:
|
||||||
|
dout[5:5] <= din;
|
||||||
|
6:
|
||||||
|
dout[6:6] <= din;
|
||||||
|
7:
|
||||||
|
dout[7:7] <= din;
|
||||||
|
8:
|
||||||
|
dout[8:8] <= din;
|
||||||
|
9:
|
||||||
|
dout[9:9] <= din;
|
||||||
|
10:
|
||||||
|
dout[10:10] <= din;
|
||||||
|
11:
|
||||||
|
dout[11:11] <= din;
|
||||||
|
12:
|
||||||
|
dout[12:12] <= din;
|
||||||
|
13:
|
||||||
|
dout[13:13] <= din;
|
||||||
|
14:
|
||||||
|
dout[14:14] <= din;
|
||||||
|
15:
|
||||||
|
dout[15:15] <= din;
|
||||||
|
endcase
|
||||||
|
case (({(ctrl)*(5'b 00101)})+(0))
|
||||||
|
0:
|
||||||
|
dout[0:0] <= din;
|
||||||
|
1:
|
||||||
|
dout[1:1] <= din;
|
||||||
|
2:
|
||||||
|
dout[2:2] <= din;
|
||||||
|
3:
|
||||||
|
dout[3:3] <= din;
|
||||||
|
4:
|
||||||
|
dout[4:4] <= din;
|
||||||
|
5:
|
||||||
|
dout[5:5] <= din;
|
||||||
|
6:
|
||||||
|
dout[6:6] <= din;
|
||||||
|
7:
|
||||||
|
dout[7:7] <= din;
|
||||||
|
8:
|
||||||
|
dout[8:8] <= din;
|
||||||
|
9:
|
||||||
|
dout[9:9] <= din;
|
||||||
|
10:
|
||||||
|
dout[10:10] <= din;
|
||||||
|
11:
|
||||||
|
dout[11:11] <= din;
|
||||||
|
12:
|
||||||
|
dout[12:12] <= din;
|
||||||
|
13:
|
||||||
|
dout[13:13] <= din;
|
||||||
|
14:
|
||||||
|
dout[14:14] <= din;
|
||||||
|
15:
|
||||||
|
dout[15:15] <= din;
|
||||||
|
endcase
|
||||||
|
case (({(ctrl)*(5'b 00110)})+(0))
|
||||||
|
0:
|
||||||
|
dout[0:0] <= din;
|
||||||
|
1:
|
||||||
|
dout[1:1] <= din;
|
||||||
|
2:
|
||||||
|
dout[2:2] <= din;
|
||||||
|
3:
|
||||||
|
dout[3:3] <= din;
|
||||||
|
4:
|
||||||
|
dout[4:4] <= din;
|
||||||
|
5:
|
||||||
|
dout[5:5] <= din;
|
||||||
|
6:
|
||||||
|
dout[6:6] <= din;
|
||||||
|
7:
|
||||||
|
dout[7:7] <= din;
|
||||||
|
8:
|
||||||
|
dout[8:8] <= din;
|
||||||
|
9:
|
||||||
|
dout[9:9] <= din;
|
||||||
|
10:
|
||||||
|
dout[10:10] <= din;
|
||||||
|
11:
|
||||||
|
dout[11:11] <= din;
|
||||||
|
12:
|
||||||
|
dout[12:12] <= din;
|
||||||
|
13:
|
||||||
|
dout[13:13] <= din;
|
||||||
|
14:
|
||||||
|
dout[14:14] <= din;
|
||||||
|
15:
|
||||||
|
dout[15:15] <= din;
|
||||||
|
endcase
|
||||||
|
case (({(ctrl)*(5'b 00111)})+(0))
|
||||||
|
0:
|
||||||
|
dout[0:0] <= din;
|
||||||
|
1:
|
||||||
|
dout[1:1] <= din;
|
||||||
|
2:
|
||||||
|
dout[2:2] <= din;
|
||||||
|
3:
|
||||||
|
dout[3:3] <= din;
|
||||||
|
4:
|
||||||
|
dout[4:4] <= din;
|
||||||
|
5:
|
||||||
|
dout[5:5] <= din;
|
||||||
|
6:
|
||||||
|
dout[6:6] <= din;
|
||||||
|
7:
|
||||||
|
dout[7:7] <= din;
|
||||||
|
8:
|
||||||
|
dout[8:8] <= din;
|
||||||
|
9:
|
||||||
|
dout[9:9] <= din;
|
||||||
|
10:
|
||||||
|
dout[10:10] <= din;
|
||||||
|
11:
|
||||||
|
dout[11:11] <= din;
|
||||||
|
12:
|
||||||
|
dout[12:12] <= din;
|
||||||
|
13:
|
||||||
|
dout[13:13] <= din;
|
||||||
|
14:
|
||||||
|
dout[14:14] <= din;
|
||||||
|
15:
|
||||||
|
dout[15:15] <= din;
|
||||||
|
endcase
|
||||||
|
case (({(ctrl)*(5'b 01000)})+(0))
|
||||||
|
0:
|
||||||
|
dout[0:0] <= din;
|
||||||
|
1:
|
||||||
|
dout[1:1] <= din;
|
||||||
|
2:
|
||||||
|
dout[2:2] <= din;
|
||||||
|
3:
|
||||||
|
dout[3:3] <= din;
|
||||||
|
4:
|
||||||
|
dout[4:4] <= din;
|
||||||
|
5:
|
||||||
|
dout[5:5] <= din;
|
||||||
|
6:
|
||||||
|
dout[6:6] <= din;
|
||||||
|
7:
|
||||||
|
dout[7:7] <= din;
|
||||||
|
8:
|
||||||
|
dout[8:8] <= din;
|
||||||
|
9:
|
||||||
|
dout[9:9] <= din;
|
||||||
|
10:
|
||||||
|
dout[10:10] <= din;
|
||||||
|
11:
|
||||||
|
dout[11:11] <= din;
|
||||||
|
12:
|
||||||
|
dout[12:12] <= din;
|
||||||
|
13:
|
||||||
|
dout[13:13] <= din;
|
||||||
|
14:
|
||||||
|
dout[14:14] <= din;
|
||||||
|
15:
|
||||||
|
dout[15:15] <= din;
|
||||||
|
endcase
|
||||||
|
case (({(ctrl)*(5'b 01001)})+(0))
|
||||||
|
0:
|
||||||
|
dout[0:0] <= din;
|
||||||
|
1:
|
||||||
|
dout[1:1] <= din;
|
||||||
|
2:
|
||||||
|
dout[2:2] <= din;
|
||||||
|
3:
|
||||||
|
dout[3:3] <= din;
|
||||||
|
4:
|
||||||
|
dout[4:4] <= din;
|
||||||
|
5:
|
||||||
|
dout[5:5] <= din;
|
||||||
|
6:
|
||||||
|
dout[6:6] <= din;
|
||||||
|
7:
|
||||||
|
dout[7:7] <= din;
|
||||||
|
8:
|
||||||
|
dout[8:8] <= din;
|
||||||
|
9:
|
||||||
|
dout[9:9] <= din;
|
||||||
|
10:
|
||||||
|
dout[10:10] <= din;
|
||||||
|
11:
|
||||||
|
dout[11:11] <= din;
|
||||||
|
12:
|
||||||
|
dout[12:12] <= din;
|
||||||
|
13:
|
||||||
|
dout[13:13] <= din;
|
||||||
|
14:
|
||||||
|
dout[14:14] <= din;
|
||||||
|
15:
|
||||||
|
dout[15:15] <= din;
|
||||||
|
endcase
|
||||||
|
case (({(ctrl)*(5'b 01010)})+(0))
|
||||||
|
0:
|
||||||
|
dout[0:0] <= din;
|
||||||
|
1:
|
||||||
|
dout[1:1] <= din;
|
||||||
|
2:
|
||||||
|
dout[2:2] <= din;
|
||||||
|
3:
|
||||||
|
dout[3:3] <= din;
|
||||||
|
4:
|
||||||
|
dout[4:4] <= din;
|
||||||
|
5:
|
||||||
|
dout[5:5] <= din;
|
||||||
|
6:
|
||||||
|
dout[6:6] <= din;
|
||||||
|
7:
|
||||||
|
dout[7:7] <= din;
|
||||||
|
8:
|
||||||
|
dout[8:8] <= din;
|
||||||
|
9:
|
||||||
|
dout[9:9] <= din;
|
||||||
|
10:
|
||||||
|
dout[10:10] <= din;
|
||||||
|
11:
|
||||||
|
dout[11:11] <= din;
|
||||||
|
12:
|
||||||
|
dout[12:12] <= din;
|
||||||
|
13:
|
||||||
|
dout[13:13] <= din;
|
||||||
|
14:
|
||||||
|
dout[14:14] <= din;
|
||||||
|
15:
|
||||||
|
dout[15:15] <= din;
|
||||||
|
endcase
|
||||||
|
case (({(ctrl)*(5'b 01011)})+(0))
|
||||||
|
0:
|
||||||
|
dout[0:0] <= din;
|
||||||
|
1:
|
||||||
|
dout[1:1] <= din;
|
||||||
|
2:
|
||||||
|
dout[2:2] <= din;
|
||||||
|
3:
|
||||||
|
dout[3:3] <= din;
|
||||||
|
4:
|
||||||
|
dout[4:4] <= din;
|
||||||
|
5:
|
||||||
|
dout[5:5] <= din;
|
||||||
|
6:
|
||||||
|
dout[6:6] <= din;
|
||||||
|
7:
|
||||||
|
dout[7:7] <= din;
|
||||||
|
8:
|
||||||
|
dout[8:8] <= din;
|
||||||
|
9:
|
||||||
|
dout[9:9] <= din;
|
||||||
|
10:
|
||||||
|
dout[10:10] <= din;
|
||||||
|
11:
|
||||||
|
dout[11:11] <= din;
|
||||||
|
12:
|
||||||
|
dout[12:12] <= din;
|
||||||
|
13:
|
||||||
|
dout[13:13] <= din;
|
||||||
|
14:
|
||||||
|
dout[14:14] <= din;
|
||||||
|
15:
|
||||||
|
dout[15:15] <= din;
|
||||||
|
endcase
|
||||||
|
case (({(ctrl)*(5'b 01100)})+(0))
|
||||||
|
0:
|
||||||
|
dout[0:0] <= din;
|
||||||
|
1:
|
||||||
|
dout[1:1] <= din;
|
||||||
|
2:
|
||||||
|
dout[2:2] <= din;
|
||||||
|
3:
|
||||||
|
dout[3:3] <= din;
|
||||||
|
4:
|
||||||
|
dout[4:4] <= din;
|
||||||
|
5:
|
||||||
|
dout[5:5] <= din;
|
||||||
|
6:
|
||||||
|
dout[6:6] <= din;
|
||||||
|
7:
|
||||||
|
dout[7:7] <= din;
|
||||||
|
8:
|
||||||
|
dout[8:8] <= din;
|
||||||
|
9:
|
||||||
|
dout[9:9] <= din;
|
||||||
|
10:
|
||||||
|
dout[10:10] <= din;
|
||||||
|
11:
|
||||||
|
dout[11:11] <= din;
|
||||||
|
12:
|
||||||
|
dout[12:12] <= din;
|
||||||
|
13:
|
||||||
|
dout[13:13] <= din;
|
||||||
|
14:
|
||||||
|
dout[14:14] <= din;
|
||||||
|
15:
|
||||||
|
dout[15:15] <= din;
|
||||||
|
endcase
|
||||||
|
case (({(ctrl)*(5'b 01101)})+(0))
|
||||||
|
0:
|
||||||
|
dout[0:0] <= din;
|
||||||
|
1:
|
||||||
|
dout[1:1] <= din;
|
||||||
|
2:
|
||||||
|
dout[2:2] <= din;
|
||||||
|
3:
|
||||||
|
dout[3:3] <= din;
|
||||||
|
4:
|
||||||
|
dout[4:4] <= din;
|
||||||
|
5:
|
||||||
|
dout[5:5] <= din;
|
||||||
|
6:
|
||||||
|
dout[6:6] <= din;
|
||||||
|
7:
|
||||||
|
dout[7:7] <= din;
|
||||||
|
8:
|
||||||
|
dout[8:8] <= din;
|
||||||
|
9:
|
||||||
|
dout[9:9] <= din;
|
||||||
|
10:
|
||||||
|
dout[10:10] <= din;
|
||||||
|
11:
|
||||||
|
dout[11:11] <= din;
|
||||||
|
12:
|
||||||
|
dout[12:12] <= din;
|
||||||
|
13:
|
||||||
|
dout[13:13] <= din;
|
||||||
|
14:
|
||||||
|
dout[14:14] <= din;
|
||||||
|
15:
|
||||||
|
dout[15:15] <= din;
|
||||||
|
endcase
|
||||||
|
case (({(ctrl)*(5'b 01110)})+(0))
|
||||||
|
0:
|
||||||
|
dout[0:0] <= din;
|
||||||
|
1:
|
||||||
|
dout[1:1] <= din;
|
||||||
|
2:
|
||||||
|
dout[2:2] <= din;
|
||||||
|
3:
|
||||||
|
dout[3:3] <= din;
|
||||||
|
4:
|
||||||
|
dout[4:4] <= din;
|
||||||
|
5:
|
||||||
|
dout[5:5] <= din;
|
||||||
|
6:
|
||||||
|
dout[6:6] <= din;
|
||||||
|
7:
|
||||||
|
dout[7:7] <= din;
|
||||||
|
8:
|
||||||
|
dout[8:8] <= din;
|
||||||
|
9:
|
||||||
|
dout[9:9] <= din;
|
||||||
|
10:
|
||||||
|
dout[10:10] <= din;
|
||||||
|
11:
|
||||||
|
dout[11:11] <= din;
|
||||||
|
12:
|
||||||
|
dout[12:12] <= din;
|
||||||
|
13:
|
||||||
|
dout[13:13] <= din;
|
||||||
|
14:
|
||||||
|
dout[14:14] <= din;
|
||||||
|
15:
|
||||||
|
dout[15:15] <= din;
|
||||||
|
endcase
|
||||||
|
case (({(ctrl)*(5'b 01111)})+(0))
|
||||||
|
0:
|
||||||
|
dout[0:0] <= din;
|
||||||
|
1:
|
||||||
|
dout[1:1] <= din;
|
||||||
|
2:
|
||||||
|
dout[2:2] <= din;
|
||||||
|
3:
|
||||||
|
dout[3:3] <= din;
|
||||||
|
4:
|
||||||
|
dout[4:4] <= din;
|
||||||
|
5:
|
||||||
|
dout[5:5] <= din;
|
||||||
|
6:
|
||||||
|
dout[6:6] <= din;
|
||||||
|
7:
|
||||||
|
dout[7:7] <= din;
|
||||||
|
8:
|
||||||
|
dout[8:8] <= din;
|
||||||
|
9:
|
||||||
|
dout[9:9] <= din;
|
||||||
|
10:
|
||||||
|
dout[10:10] <= din;
|
||||||
|
11:
|
||||||
|
dout[11:11] <= din;
|
||||||
|
12:
|
||||||
|
dout[12:12] <= din;
|
||||||
|
13:
|
||||||
|
dout[13:13] <= din;
|
||||||
|
14:
|
||||||
|
dout[14:14] <= din;
|
||||||
|
15:
|
||||||
|
dout[15:15] <= din;
|
||||||
|
endcase
|
||||||
|
sel = 5'b 10000;
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
endmodule
|
19
tests/various/dynamic_part_select/multiple_blocking.v
Normal file
19
tests/various/dynamic_part_select/multiple_blocking.v
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
module multiple_blocking #(parameter WIDTH=32, SELW=1, CTRLW=$clog2(WIDTH), DINW=2**SELW)
|
||||||
|
(input clk,
|
||||||
|
input [CTRLW-1:0] ctrl,
|
||||||
|
input [DINW-1:0] din,
|
||||||
|
input [SELW-1:0] sel,
|
||||||
|
output reg [WIDTH-1:0] dout);
|
||||||
|
|
||||||
|
localparam SLICE = WIDTH/(SELW**2);
|
||||||
|
reg [CTRLW:0] a;
|
||||||
|
reg [SELW-1:0] b;
|
||||||
|
reg [DINW:0] c;
|
||||||
|
always @(posedge clk) begin
|
||||||
|
a = ctrl + 1;
|
||||||
|
b = sel - 1;
|
||||||
|
c = ~din;
|
||||||
|
dout = dout + 1;
|
||||||
|
dout[a*b+:SLICE] = c;
|
||||||
|
end
|
||||||
|
endmodule
|
83
tests/various/dynamic_part_select/multiple_blocking_gate.v
Normal file
83
tests/various/dynamic_part_select/multiple_blocking_gate.v
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
module multiple_blocking_gate (clk, ctrl, din, sel, dout);
|
||||||
|
input clk;
|
||||||
|
input [4:0] ctrl;
|
||||||
|
input [1:0] din;
|
||||||
|
input [0:0] sel;
|
||||||
|
output reg [31:0] dout;
|
||||||
|
reg [5:0] a;
|
||||||
|
reg [0:0] b;
|
||||||
|
reg [2:0] c;
|
||||||
|
always @(posedge clk)
|
||||||
|
begin
|
||||||
|
a = (ctrl)+(1);
|
||||||
|
b = (sel)-(1);
|
||||||
|
c = ~(din);
|
||||||
|
dout = (dout)+(1);
|
||||||
|
case (({(a)*(b)})+(0))
|
||||||
|
0:
|
||||||
|
dout[31:0] = c;
|
||||||
|
1:
|
||||||
|
dout[31:1] = c;
|
||||||
|
2:
|
||||||
|
dout[31:2] = c;
|
||||||
|
3:
|
||||||
|
dout[31:3] = c;
|
||||||
|
4:
|
||||||
|
dout[31:4] = c;
|
||||||
|
5:
|
||||||
|
dout[31:5] = c;
|
||||||
|
6:
|
||||||
|
dout[31:6] = c;
|
||||||
|
7:
|
||||||
|
dout[31:7] = c;
|
||||||
|
8:
|
||||||
|
dout[31:8] = c;
|
||||||
|
9:
|
||||||
|
dout[31:9] = c;
|
||||||
|
10:
|
||||||
|
dout[31:10] = c;
|
||||||
|
11:
|
||||||
|
dout[31:11] = c;
|
||||||
|
12:
|
||||||
|
dout[31:12] = c;
|
||||||
|
13:
|
||||||
|
dout[31:13] = c;
|
||||||
|
14:
|
||||||
|
dout[31:14] = c;
|
||||||
|
15:
|
||||||
|
dout[31:15] = c;
|
||||||
|
16:
|
||||||
|
dout[31:16] = c;
|
||||||
|
17:
|
||||||
|
dout[31:17] = c;
|
||||||
|
18:
|
||||||
|
dout[31:18] = c;
|
||||||
|
19:
|
||||||
|
dout[31:19] = c;
|
||||||
|
20:
|
||||||
|
dout[31:20] = c;
|
||||||
|
21:
|
||||||
|
dout[31:21] = c;
|
||||||
|
22:
|
||||||
|
dout[31:22] = c;
|
||||||
|
23:
|
||||||
|
dout[31:23] = c;
|
||||||
|
24:
|
||||||
|
dout[31:24] = c;
|
||||||
|
25:
|
||||||
|
dout[31:25] = c;
|
||||||
|
26:
|
||||||
|
dout[31:26] = c;
|
||||||
|
27:
|
||||||
|
dout[31:27] = c;
|
||||||
|
28:
|
||||||
|
dout[31:28] = c;
|
||||||
|
29:
|
||||||
|
dout[31:29] = c;
|
||||||
|
30:
|
||||||
|
dout[31:30] = c;
|
||||||
|
31:
|
||||||
|
dout[31:31] = c;
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
endmodule
|
14
tests/various/dynamic_part_select/nonblocking.v
Normal file
14
tests/various/dynamic_part_select/nonblocking.v
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
module nonblocking #(parameter WIDTH=32, SELW=1, CTRLW=$clog2(WIDTH), DINW=2**SELW)
|
||||||
|
(input clk,
|
||||||
|
input [CTRLW-1:0] ctrl,
|
||||||
|
input [DINW-1:0] din,
|
||||||
|
input [SELW-1:0] sel,
|
||||||
|
output reg [WIDTH-1:0] dout);
|
||||||
|
|
||||||
|
localparam SLICE = WIDTH/(SELW**2);
|
||||||
|
always @(posedge clk) begin
|
||||||
|
dout <= dout + 1;
|
||||||
|
dout[ctrl*sel+:SLICE] <= din ;
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
77
tests/various/dynamic_part_select/nonblocking_gate.v
Normal file
77
tests/various/dynamic_part_select/nonblocking_gate.v
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
module nonblocking_gate (clk, ctrl, din, sel, dout);
|
||||||
|
input clk;
|
||||||
|
input [4:0] ctrl;
|
||||||
|
input [1:0] din;
|
||||||
|
input [0:0] sel;
|
||||||
|
output reg [31:0] dout;
|
||||||
|
always @(posedge clk)
|
||||||
|
begin
|
||||||
|
dout <= (dout)+(1);
|
||||||
|
case (({(ctrl)*(sel)})+(0))
|
||||||
|
0:
|
||||||
|
dout[31:0] <= din;
|
||||||
|
1:
|
||||||
|
dout[31:1] <= din;
|
||||||
|
2:
|
||||||
|
dout[31:2] <= din;
|
||||||
|
3:
|
||||||
|
dout[31:3] <= din;
|
||||||
|
4:
|
||||||
|
dout[31:4] <= din;
|
||||||
|
5:
|
||||||
|
dout[31:5] <= din;
|
||||||
|
6:
|
||||||
|
dout[31:6] <= din;
|
||||||
|
7:
|
||||||
|
dout[31:7] <= din;
|
||||||
|
8:
|
||||||
|
dout[31:8] <= din;
|
||||||
|
9:
|
||||||
|
dout[31:9] <= din;
|
||||||
|
10:
|
||||||
|
dout[31:10] <= din;
|
||||||
|
11:
|
||||||
|
dout[31:11] <= din;
|
||||||
|
12:
|
||||||
|
dout[31:12] <= din;
|
||||||
|
13:
|
||||||
|
dout[31:13] <= din;
|
||||||
|
14:
|
||||||
|
dout[31:14] <= din;
|
||||||
|
15:
|
||||||
|
dout[31:15] <= din;
|
||||||
|
16:
|
||||||
|
dout[31:16] <= din;
|
||||||
|
17:
|
||||||
|
dout[31:17] <= din;
|
||||||
|
18:
|
||||||
|
dout[31:18] <= din;
|
||||||
|
19:
|
||||||
|
dout[31:19] <= din;
|
||||||
|
20:
|
||||||
|
dout[31:20] <= din;
|
||||||
|
21:
|
||||||
|
dout[31:21] <= din;
|
||||||
|
22:
|
||||||
|
dout[31:22] <= din;
|
||||||
|
23:
|
||||||
|
dout[31:23] <= din;
|
||||||
|
24:
|
||||||
|
dout[31:24] <= din;
|
||||||
|
25:
|
||||||
|
dout[31:25] <= din;
|
||||||
|
26:
|
||||||
|
dout[31:26] <= din;
|
||||||
|
27:
|
||||||
|
dout[31:27] <= din;
|
||||||
|
28:
|
||||||
|
dout[31:28] <= din;
|
||||||
|
29:
|
||||||
|
dout[31:29] <= din;
|
||||||
|
30:
|
||||||
|
dout[31:30] <= din;
|
||||||
|
31:
|
||||||
|
dout[31:31] <= din;
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
endmodule
|
12
tests/various/dynamic_part_select/original.v
Normal file
12
tests/various/dynamic_part_select/original.v
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
module original #(parameter WIDTH=32, SELW=1, CTRLW=$clog2(WIDTH), DINW=2**SELW)
|
||||||
|
(input clk,
|
||||||
|
input [CTRLW-1:0] ctrl,
|
||||||
|
input [DINW-1:0] din,
|
||||||
|
input [SELW-1:0] sel,
|
||||||
|
output reg [WIDTH-1:0] dout);
|
||||||
|
localparam SLICE = WIDTH/(SELW**2);
|
||||||
|
always @(posedge clk)
|
||||||
|
begin
|
||||||
|
dout[ctrl*sel+:SLICE] <= din ;
|
||||||
|
end
|
||||||
|
endmodule
|
74
tests/various/dynamic_part_select/original_gate.v
Normal file
74
tests/various/dynamic_part_select/original_gate.v
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
module original_gate (clk, ctrl, din, sel, dout);
|
||||||
|
input clk;
|
||||||
|
input [4:0] ctrl;
|
||||||
|
input [1:0] din;
|
||||||
|
input [0:0] sel;
|
||||||
|
output reg [31:0] dout;
|
||||||
|
always @(posedge clk)
|
||||||
|
case (({(ctrl)*(sel)})+(0))
|
||||||
|
0:
|
||||||
|
dout[31:0] <= din;
|
||||||
|
1:
|
||||||
|
dout[31:1] <= din;
|
||||||
|
2:
|
||||||
|
dout[31:2] <= din;
|
||||||
|
3:
|
||||||
|
dout[31:3] <= din;
|
||||||
|
4:
|
||||||
|
dout[31:4] <= din;
|
||||||
|
5:
|
||||||
|
dout[31:5] <= din;
|
||||||
|
6:
|
||||||
|
dout[31:6] <= din;
|
||||||
|
7:
|
||||||
|
dout[31:7] <= din;
|
||||||
|
8:
|
||||||
|
dout[31:8] <= din;
|
||||||
|
9:
|
||||||
|
dout[31:9] <= din;
|
||||||
|
10:
|
||||||
|
dout[31:10] <= din;
|
||||||
|
11:
|
||||||
|
dout[31:11] <= din;
|
||||||
|
12:
|
||||||
|
dout[31:12] <= din;
|
||||||
|
13:
|
||||||
|
dout[31:13] <= din;
|
||||||
|
14:
|
||||||
|
dout[31:14] <= din;
|
||||||
|
15:
|
||||||
|
dout[31:15] <= din;
|
||||||
|
16:
|
||||||
|
dout[31:16] <= din;
|
||||||
|
17:
|
||||||
|
dout[31:17] <= din;
|
||||||
|
18:
|
||||||
|
dout[31:18] <= din;
|
||||||
|
19:
|
||||||
|
dout[31:19] <= din;
|
||||||
|
20:
|
||||||
|
dout[31:20] <= din;
|
||||||
|
21:
|
||||||
|
dout[31:21] <= din;
|
||||||
|
22:
|
||||||
|
dout[31:22] <= din;
|
||||||
|
23:
|
||||||
|
dout[31:23] <= din;
|
||||||
|
24:
|
||||||
|
dout[31:24] <= din;
|
||||||
|
25:
|
||||||
|
dout[31:25] <= din;
|
||||||
|
26:
|
||||||
|
dout[31:26] <= din;
|
||||||
|
27:
|
||||||
|
dout[31:27] <= din;
|
||||||
|
28:
|
||||||
|
dout[31:28] <= din;
|
||||||
|
29:
|
||||||
|
dout[31:29] <= din;
|
||||||
|
30:
|
||||||
|
dout[31:30] <= din;
|
||||||
|
31:
|
||||||
|
dout[31:31] <= din;
|
||||||
|
endcase
|
||||||
|
endmodule
|
23
tests/various/dynamic_part_select/reset_test.v
Normal file
23
tests/various/dynamic_part_select/reset_test.v
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
module reset_test #(parameter WIDTH=32, SELW=1, CTRLW=$clog2(WIDTH), DINW=2**SELW)
|
||||||
|
(input clk,
|
||||||
|
input [CTRLW-1:0] ctrl,
|
||||||
|
input [DINW-1:0] din,
|
||||||
|
input [SELW-1:0] sel,
|
||||||
|
output reg [WIDTH-1:0] dout);
|
||||||
|
|
||||||
|
reg [SELW:0] i;
|
||||||
|
wire [SELW-1:0] rval = {reset, {SELW-1{1'b0}}};
|
||||||
|
localparam SLICE = WIDTH/(SELW**2);
|
||||||
|
// Doing exotic reset. masking 2 LSB bits to 0, 6 MSB bits to 1 for
|
||||||
|
// whatever reason.
|
||||||
|
always @(posedge clk) begin
|
||||||
|
if (reset) begin: reset_mask
|
||||||
|
for (i = 0; i < {SELW{1'b1}}; i=i+1) begin
|
||||||
|
dout[i*rval+:SLICE] <= 32'hDEAD;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
//else begin
|
||||||
|
dout[ctrl*sel+:SLICE] <= din;
|
||||||
|
//end
|
||||||
|
end
|
||||||
|
endmodule
|
151
tests/various/dynamic_part_select/reset_test_gate.v
Normal file
151
tests/various/dynamic_part_select/reset_test_gate.v
Normal file
|
@ -0,0 +1,151 @@
|
||||||
|
module reset_test_gate (clk, ctrl, din, sel, dout);
|
||||||
|
input clk;
|
||||||
|
input [4:0] ctrl;
|
||||||
|
input [1:0] din;
|
||||||
|
input [0:0] sel;
|
||||||
|
output reg [31:0] dout;
|
||||||
|
reg [1:0] i;
|
||||||
|
wire [0:0] rval;
|
||||||
|
assign rval = {reset, 1'b0 };
|
||||||
|
always @(posedge clk)
|
||||||
|
begin
|
||||||
|
case (|(reset))
|
||||||
|
1'b 1:
|
||||||
|
begin
|
||||||
|
case (({(0)*(rval)})+(0))
|
||||||
|
0:
|
||||||
|
dout[31:0] <= 57005;
|
||||||
|
1:
|
||||||
|
dout[31:1] <= 57005;
|
||||||
|
2:
|
||||||
|
dout[31:2] <= 57005;
|
||||||
|
3:
|
||||||
|
dout[31:3] <= 57005;
|
||||||
|
4:
|
||||||
|
dout[31:4] <= 57005;
|
||||||
|
5:
|
||||||
|
dout[31:5] <= 57005;
|
||||||
|
6:
|
||||||
|
dout[31:6] <= 57005;
|
||||||
|
7:
|
||||||
|
dout[31:7] <= 57005;
|
||||||
|
8:
|
||||||
|
dout[31:8] <= 57005;
|
||||||
|
9:
|
||||||
|
dout[31:9] <= 57005;
|
||||||
|
10:
|
||||||
|
dout[31:10] <= 57005;
|
||||||
|
11:
|
||||||
|
dout[31:11] <= 57005;
|
||||||
|
12:
|
||||||
|
dout[31:12] <= 57005;
|
||||||
|
13:
|
||||||
|
dout[31:13] <= 57005;
|
||||||
|
14:
|
||||||
|
dout[31:14] <= 57005;
|
||||||
|
15:
|
||||||
|
dout[31:15] <= 57005;
|
||||||
|
16:
|
||||||
|
dout[31:16] <= 57005;
|
||||||
|
17:
|
||||||
|
dout[31:17] <= 57005;
|
||||||
|
18:
|
||||||
|
dout[31:18] <= 57005;
|
||||||
|
19:
|
||||||
|
dout[31:19] <= 57005;
|
||||||
|
20:
|
||||||
|
dout[31:20] <= 57005;
|
||||||
|
21:
|
||||||
|
dout[31:21] <= 57005;
|
||||||
|
22:
|
||||||
|
dout[31:22] <= 57005;
|
||||||
|
23:
|
||||||
|
dout[31:23] <= 57005;
|
||||||
|
24:
|
||||||
|
dout[31:24] <= 57005;
|
||||||
|
25:
|
||||||
|
dout[31:25] <= 57005;
|
||||||
|
26:
|
||||||
|
dout[31:26] <= 57005;
|
||||||
|
27:
|
||||||
|
dout[31:27] <= 57005;
|
||||||
|
28:
|
||||||
|
dout[31:28] <= 57005;
|
||||||
|
29:
|
||||||
|
dout[31:29] <= 57005;
|
||||||
|
30:
|
||||||
|
dout[31:30] <= 57005;
|
||||||
|
31:
|
||||||
|
dout[31:31] <= 57005;
|
||||||
|
endcase
|
||||||
|
i = 1;
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
case (({(ctrl)*(sel)})+(0))
|
||||||
|
0:
|
||||||
|
dout[31:0] <= din;
|
||||||
|
1:
|
||||||
|
dout[31:1] <= din;
|
||||||
|
2:
|
||||||
|
dout[31:2] <= din;
|
||||||
|
3:
|
||||||
|
dout[31:3] <= din;
|
||||||
|
4:
|
||||||
|
dout[31:4] <= din;
|
||||||
|
5:
|
||||||
|
dout[31:5] <= din;
|
||||||
|
6:
|
||||||
|
dout[31:6] <= din;
|
||||||
|
7:
|
||||||
|
dout[31:7] <= din;
|
||||||
|
8:
|
||||||
|
dout[31:8] <= din;
|
||||||
|
9:
|
||||||
|
dout[31:9] <= din;
|
||||||
|
10:
|
||||||
|
dout[31:10] <= din;
|
||||||
|
11:
|
||||||
|
dout[31:11] <= din;
|
||||||
|
12:
|
||||||
|
dout[31:12] <= din;
|
||||||
|
13:
|
||||||
|
dout[31:13] <= din;
|
||||||
|
14:
|
||||||
|
dout[31:14] <= din;
|
||||||
|
15:
|
||||||
|
dout[31:15] <= din;
|
||||||
|
16:
|
||||||
|
dout[31:16] <= din;
|
||||||
|
17:
|
||||||
|
dout[31:17] <= din;
|
||||||
|
18:
|
||||||
|
dout[31:18] <= din;
|
||||||
|
19:
|
||||||
|
dout[31:19] <= din;
|
||||||
|
20:
|
||||||
|
dout[31:20] <= din;
|
||||||
|
21:
|
||||||
|
dout[31:21] <= din;
|
||||||
|
22:
|
||||||
|
dout[31:22] <= din;
|
||||||
|
23:
|
||||||
|
dout[31:23] <= din;
|
||||||
|
24:
|
||||||
|
dout[31:24] <= din;
|
||||||
|
25:
|
||||||
|
dout[31:25] <= din;
|
||||||
|
26:
|
||||||
|
dout[31:26] <= din;
|
||||||
|
27:
|
||||||
|
dout[31:27] <= din;
|
||||||
|
28:
|
||||||
|
dout[31:28] <= din;
|
||||||
|
29:
|
||||||
|
dout[31:29] <= din;
|
||||||
|
30:
|
||||||
|
dout[31:30] <= din;
|
||||||
|
31:
|
||||||
|
dout[31:31] <= din;
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
endmodule
|
13
tests/various/dynamic_part_select/reversed.v
Normal file
13
tests/various/dynamic_part_select/reversed.v
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
module reversed #(parameter WIDTH=32, SELW=4, CTRLW=$clog2(WIDTH), DINW=2**SELW)
|
||||||
|
(input clk,
|
||||||
|
input [CTRLW-1:0] ctrl,
|
||||||
|
input [DINW-1:0] din,
|
||||||
|
input [SELW-1:0] sel,
|
||||||
|
output reg [WIDTH-1:0] dout);
|
||||||
|
|
||||||
|
localparam SLICE = WIDTH/(SELW**2);
|
||||||
|
always @(posedge clk) begin
|
||||||
|
dout[(WIDTH-ctrl*sel)-:SLICE] <= din;
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
|
|
74
tests/various/dynamic_part_select/reversed_gate.v
Normal file
74
tests/various/dynamic_part_select/reversed_gate.v
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
module reversed_gate (clk, ctrl, din, sel, dout);
|
||||||
|
input clk;
|
||||||
|
input [4:0] ctrl;
|
||||||
|
input [15:0] din;
|
||||||
|
input [3:0] sel;
|
||||||
|
output reg [31:0] dout;
|
||||||
|
always @(posedge clk)
|
||||||
|
case ((({(32)-((ctrl)*(sel))})+(1))-(2))
|
||||||
|
0:
|
||||||
|
dout[1:0] <= din;
|
||||||
|
1:
|
||||||
|
dout[2:1] <= din;
|
||||||
|
2:
|
||||||
|
dout[3:2] <= din;
|
||||||
|
3:
|
||||||
|
dout[4:3] <= din;
|
||||||
|
4:
|
||||||
|
dout[5:4] <= din;
|
||||||
|
5:
|
||||||
|
dout[6:5] <= din;
|
||||||
|
6:
|
||||||
|
dout[7:6] <= din;
|
||||||
|
7:
|
||||||
|
dout[8:7] <= din;
|
||||||
|
8:
|
||||||
|
dout[9:8] <= din;
|
||||||
|
9:
|
||||||
|
dout[10:9] <= din;
|
||||||
|
10:
|
||||||
|
dout[11:10] <= din;
|
||||||
|
11:
|
||||||
|
dout[12:11] <= din;
|
||||||
|
12:
|
||||||
|
dout[13:12] <= din;
|
||||||
|
13:
|
||||||
|
dout[14:13] <= din;
|
||||||
|
14:
|
||||||
|
dout[15:14] <= din;
|
||||||
|
15:
|
||||||
|
dout[16:15] <= din;
|
||||||
|
16:
|
||||||
|
dout[17:16] <= din;
|
||||||
|
17:
|
||||||
|
dout[18:17] <= din;
|
||||||
|
18:
|
||||||
|
dout[19:18] <= din;
|
||||||
|
19:
|
||||||
|
dout[20:19] <= din;
|
||||||
|
20:
|
||||||
|
dout[21:20] <= din;
|
||||||
|
21:
|
||||||
|
dout[22:21] <= din;
|
||||||
|
22:
|
||||||
|
dout[23:22] <= din;
|
||||||
|
23:
|
||||||
|
dout[24:23] <= din;
|
||||||
|
24:
|
||||||
|
dout[25:24] <= din;
|
||||||
|
25:
|
||||||
|
dout[26:25] <= din;
|
||||||
|
26:
|
||||||
|
dout[27:26] <= din;
|
||||||
|
27:
|
||||||
|
dout[28:27] <= din;
|
||||||
|
28:
|
||||||
|
dout[29:28] <= din;
|
||||||
|
29:
|
||||||
|
dout[30:29] <= din;
|
||||||
|
30:
|
||||||
|
dout[31:30] <= din;
|
||||||
|
31:
|
||||||
|
dout[31:31] <= din;
|
||||||
|
endcase
|
||||||
|
endmodule
|
Loading…
Reference in a new issue