Skip to content

Commit

Permalink
Fix arrayed instances to unpacked of same size, bug1015. Fix slices o…
Browse files Browse the repository at this point in the history
…f unpacked arrays with non-zero LSBs.
  • Loading branch information
wsnyder committed Dec 16, 2015
1 parent e8b5001 commit 21cb29b
Show file tree
Hide file tree
Showing 6 changed files with 149 additions and 5 deletions.
4 changes: 4 additions & 0 deletions Changes
Expand Up @@ -35,6 +35,10 @@ indicates the contributor was also the author of the fix; Thanks!

**** Fix model restore crash, bug1013. [Jason McMullan]

**** Fix arrayed instances to unpacked of same size, bug1015. [Varun Koyyalagunta]

**** Fix slices of unpacked arrays with non-zero LSBs.


* Verilator 3.878 2015-11-01

Expand Down
17 changes: 15 additions & 2 deletions src/V3Inst.cpp
Expand Up @@ -257,7 +257,20 @@ class InstDeVisitor : public AstNVisitor {
UINFO(4," PIN "<<nodep<<endl);
int pinwidth = nodep->modVarp()->width();
int expwidth = nodep->exprp()->width();
if (expwidth == pinwidth) {
pair<uint32_t,uint32_t> pinDim = nodep->modVarp()->dtypep()->dimensions(false);
pair<uint32_t,uint32_t> expDim = nodep->exprp()->dtypep()->dimensions(false);
UINFO(4," PINVAR "<<nodep->modVarp()<<endl);
UINFO(4," EXP "<<nodep->exprp()<<endl);
UINFO(4," pinwidth ew="<<expwidth<<" pw="<<pinwidth
<<" ed="<<expDim.first<<","<<expDim.second
<<" pd="<<pinDim.first<<","<<pinDim.second<<endl);
if (expDim.first == pinDim.first && expDim.second == pinDim.second+1) {
// Connection to array, where array dimensions match the instant dimension
AstNode* exprp = nodep->exprp()->unlinkFrBack();
exprp = new AstArraySel (exprp->fileline(), exprp,
(m_instNum-m_instLsb));
nodep->exprp(exprp);
} else if (expwidth == pinwidth) {
// NOP: Arrayed instants: widths match so connect to each instance
} else if (expwidth == pinwidth*m_cellRangep->elementsConst()) {
// Arrayed instants: one bit for each of the instants (each assign is 1 pinwidth wide)
Expand All @@ -276,7 +289,7 @@ class InstDeVisitor : public AstNVisitor {
} else {
nodep->v3fatalSrc("Width mismatch; V3Width should have errored out.");
}
} else if(AstArraySel* arrselp = nodep->exprp()->castArraySel()) {
} else if (AstArraySel* arrselp = nodep->exprp()->castArraySel()) {
if (AstUnpackArrayDType* arrp = arrselp->lhsp()->dtypep()->castUnpackArrayDType()) {
if (!arrp->subDTypep()->castIfaceRefDType())
return;
Expand Down
10 changes: 7 additions & 3 deletions src/V3Slice.cpp
Expand Up @@ -99,7 +99,9 @@ class SliceCloneVisitor : public AstNVisitor {
// Reassign the bitp()
if (nodep->length() > 1) {
if (AstConst* bitp = nodep->bitp()->castConst()) {
unsigned idx = nodep->start() + m_selBits[m_vecIdx][m_depth];
AstUnpackArrayDType* adtypep = nodep->fromp()->dtypep()->skipRefp()->castUnpackArrayDType();
if (!adtypep) nodep->v3fatalSrc("slice select tried to expand an array without an ArrayDType");
unsigned idx = nodep->start() + m_selBits[m_vecIdx][m_depth] - adtypep->lsb();
AstNode* constp = new AstConst(bitp->fileline(), V3Number(bitp->fileline(), bitp->castConst()->num().width(), idx));
bitp->replaceWith(constp);
} else {
Expand Down Expand Up @@ -272,7 +274,9 @@ class SliceVisitor : public AstNVisitor {
int x = msb; msb = lsb; lsb = x;
}
UINFO(9," ArraySel-child: "<<topp<<endl);
AstArraySel* newp = new AstArraySel(nodep->fileline(), topp, new AstConst(nodep->fileline(),lsb));
AstArraySel* newp = new AstArraySel(nodep->fileline(), topp,
// "lsb-lsb": Arrays are zero-based so index 0 is always lsb
new AstConst(nodep->fileline(), lsb-lsb));
if (!newp->dtypep()) {
newp->v3fatalSrc("ArraySel dtyping failed when resolving slice"); // see ArraySel constructor
}
Expand Down Expand Up @@ -503,5 +507,5 @@ class SliceVisitor : public AstNVisitor {
void V3Slice::sliceAll(AstNetlist* rootp) {
UINFO(2,__FUNCTION__<<": "<<endl);
SliceVisitor visitor(rootp);
V3Global::dumpCheckGlobalTree("slices.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
V3Global::dumpCheckGlobalTree("slice.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
18 changes: 18 additions & 0 deletions test_regress/t/t_inst_slice.pl
@@ -0,0 +1,18 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.

compile (
);

execute (
check_finished=>1,
);

ok(1);
1;
84 changes: 84 additions & 0 deletions test_regress/t/t_inst_slice.v
@@ -0,0 +1,84 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2015 by Varun Koyyalagunta.

// bug1015
module t (/*AUTOARG*/
// Inputs
clk
);
input clk;

integer cyc=0;
reg [63:0] crc;
reg [63:0] sum;

// Take CRC data and apply to testblock inputs
wire [1:0] i = crc[1:0];
logic [1:0] o [13:10] ;

Test test (/*AUTOINST*/
// Outputs
.o (o/*[1:0].[3:0]*/),
// Inputs
.i (i[1:0]));

// Aggregate outputs into a single result vector
wire [63:0] result = {32'h0, 6'h0,o[13], 6'h0,o[12], 6'h0,o[11], 6'h0,o[10]};

// Test loop
always @ (posedge clk) begin
`ifdef TEST_VERBOSE
$write("[%0t] cyc==%0d crc=%x result=%x sum=%x\n",$time, cyc, crc, result, sum);
`endif
cyc <= cyc + 1;
crc <= {crc[62:0], crc[63]^crc[2]^crc[0]};
sum <= result ^ {sum[62:0],sum[63]^sum[2]^sum[0]};
if (cyc==0) begin
// Setup
crc <= 64'h5aef0c8d_d70a4497;
sum <= '0;
end
else if (cyc<10) begin
sum <= '0;
end
else if (cyc<90) begin
end
else if (cyc==99) begin
$write("[%0t] cyc==%0d crc=%x sum=%x\n",$time, cyc, crc, sum);
if (crc !== 64'hc77bb9b3784ea091) $stop;
// What checksum will we end up with (above print should match)
`define EXPECTED_SUM 64'hb42b2f48a0a9375a
if (sum !== `EXPECTED_SUM) $stop;
$write("*-* All Finished *-*\n");
$finish;
end
end

endmodule

module Test
(
output logic [1:0] o [3:0],
//but this works
//logic [N-1:0] o
input [1:0] i);

parameter N = 4;

logic [1:0] a [3:0]; initial a = '{2'h0,2'h1,2'h2,2'h3};

sub sub [N-1:0] (.o (o), // many-to-many
.a (a), // many-to-many
.i (i)); // many-to-one
endmodule

module sub
(
input logic [1:0] i,
input logic [1:0] a,
output logic [1:0] o
);
assign o = i + a;
endmodule
21 changes: 21 additions & 0 deletions test_regress/t/t_inst_slice_noinl.pl
@@ -0,0 +1,21 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003-2009 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.

top_filename("t/t_inst_slice.v");

compile (
v_flags2 => ["-Oi"],
);

execute (
check_finished=>1,
);

ok(1);
1;

0 comments on commit 21cb29b

Please sign in to comment.