diff --git a/src/V3EmitC.cpp b/src/V3EmitC.cpp index f763ce446..3f15b39ab 100644 --- a/src/V3EmitC.cpp +++ b/src/V3EmitC.cpp @@ -86,6 +86,13 @@ public: } void emitOpName(AstNode* nodep, const string& format, AstNode* lhsp, AstNode* rhsp, AstNode* thsp); + void emitDeclArrayBrackets(AstVar* nodep) { + // This isn't very robust and may need cleanup for other data types + for (AstUnpackArrayDType* arrayp=nodep->dtypeSkipRefp()->castUnpackArrayDType(); arrayp; + arrayp = arrayp->subDTypep()->skipRefp()->castUnpackArrayDType()) { + puts("["+cvtToStr(arrayp->elementsConst())+"]"); + } + } // VISITORS virtual void visit(AstNodeAssign* nodep, AstNUser*) { @@ -788,7 +795,7 @@ class EmitCImp : EmitCStmts { if (!m_blkChangeDetVec.empty()) puts("return __req;\n"); -// puts("__Vm_activity = true;\n"); + //puts("__Vm_activity = true;\n"); puts("}\n"); } @@ -875,7 +882,6 @@ public: void EmitCStmts::emitVarDecl(AstVar* nodep, const string& prefixIfImp) { AstBasicDType* basicp = nodep->basicp(); if (!basicp) nodep->v3fatalSrc("Unimplemented: Outputting this data type"); if (nodep->isIO()) { - bool isArray = !nodep->dtypeSkipRefp()->castBasicDType(); if (nodep->isSc()) { m_ctorVarsVec.push_back(nodep); ofp()->putAlign(nodep->isStatic(), 4); // sc stuff is a structure, so bigger alignment @@ -891,12 +897,7 @@ void EmitCStmts::emitVarDecl(AstVar* nodep, const string& prefixIfImp) { puts(">\t"); } puts(nodep->name()); - if (isArray) { - for (AstUnpackArrayDType* arrayp=nodep->dtypeSkipRefp()->castUnpackArrayDType(); arrayp; - arrayp = arrayp->subDTypep()->skipRefp()->castUnpackArrayDType()) { - puts("["+cvtToStr(arrayp->elementsConst())+"]"); - } - } + emitDeclArrayBrackets(nodep); puts(";\n"); } else { // C++ signals ofp()->putAlign(nodep->isStatic(), nodep->dtypeSkipRefp()->widthAlignBytes(), @@ -906,39 +907,23 @@ void EmitCStmts::emitVarDecl(AstVar* nodep, const string& prefixIfImp) { else if (nodep->isOutput()) puts("VL_OUT"); else nodep->v3fatalSrc("Unknown type"); - if (basicp->isQuad()) puts("64"); - else if (basicp->widthMin() <= 8) puts("8"); - else if (basicp->widthMin() <= 16) puts("16"); - else if (basicp->isWide()) puts("W"); + if (nodep->isQuad()) puts("64"); + else if (nodep->widthMin() <= 8) puts("8"); + else if (nodep->widthMin() <= 16) puts("16"); + else if (nodep->isWide()) puts("W"); - if (isArray) { - puts("("+nodep->name()); - for (AstUnpackArrayDType* arrayp=nodep->dtypeSkipRefp()->castUnpackArrayDType(); arrayp; - arrayp = arrayp->subDTypep()->skipRefp()->castUnpackArrayDType()) { - puts("["+cvtToStr(arrayp->elementsConst())+"]"); - } - puts(","+cvtToStr(basicp->msb())+","+cvtToStr(basicp->lsb())); - if (basicp->isWide()) puts(","+cvtToStr(basicp->widthWords())); - } else { - if (!basicp->isWide()) - puts("("+nodep->name() - +","+cvtToStr(basicp->msb()) - +","+cvtToStr(basicp->lsb())); - else puts("("+nodep->name() - +","+cvtToStr(basicp->msb()) - +","+cvtToStr(basicp->lsb()) - +","+cvtToStr(basicp->widthWords())); - } + puts("("+nodep->name()); + emitDeclArrayBrackets(nodep); + // If it's a packed struct/array then nodep->width is the whole thing, msb/lsb is just lowest dimension + puts(","+cvtToStr(basicp->lsb()+nodep->width()-1) + +","+cvtToStr(basicp->lsb())); + if (nodep->isWide()) puts(","+cvtToStr(nodep->widthWords())); puts(");\n"); } } else if (basicp && basicp->isOpaque()) { // strings and other fundamental c types puts(nodep->vlArgType(true,false)); - // This isn't very robust and may need cleanup for other data types - for (AstUnpackArrayDType* arrayp=nodep->dtypeSkipRefp()->castUnpackArrayDType(); arrayp; - arrayp = arrayp->subDTypep()->skipRefp()->castUnpackArrayDType()) { - puts("["+cvtToStr(arrayp->elementsConst())+"]"); - } + emitDeclArrayBrackets(nodep); puts(";\n"); } else { // Arrays need a small alignment, but may need different padding after. @@ -960,13 +945,10 @@ void EmitCStmts::emitVarDecl(AstVar* nodep, const string& prefixIfImp) { } if (prefixIfImp!="") { puts(prefixIfImp); puts("::"); } puts(nodep->name()); - // This isn't very robust and may need cleanup for other data types - for (AstUnpackArrayDType* arrayp=nodep->dtypeSkipRefp()->castUnpackArrayDType(); arrayp; - arrayp = arrayp->subDTypep()->skipRefp()->castUnpackArrayDType()) { - puts("["+cvtToStr(arrayp->elementsConst())+"]"); - } + emitDeclArrayBrackets(nodep); // If it's a packed struct/array then nodep->width is the whole thing, msb/lsb is just lowest dimension - puts(","+cvtToStr(basicp->lsb()+nodep->width())+","+cvtToStr(basicp->lsb())); + puts(","+cvtToStr(basicp->lsb()+nodep->width()-1) + +","+cvtToStr(basicp->lsb())); if (nodep->isWide()) puts(","+cvtToStr(nodep->widthWords())); puts(");\n"); } diff --git a/test_regress/t/t_mem_multi_io3.cpp b/test_regress/t/t_mem_multi_io3.cpp new file mode 100644 index 000000000..8f001d86f --- /dev/null +++ b/test_regress/t/t_mem_multi_io3.cpp @@ -0,0 +1,34 @@ +// -*- mode: C++; c-file-style: "cc-mode" -*- +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty. + +#if defined(T_MEM_MULTI_IO3_CC) +# include "Vt_mem_multi_io3_cc.h" +#elif defined(T_MEM_MULTI_IO3_SC) +# include "Vt_mem_multi_io3_sc.h" +#else +# error "Unknown test" +#endif + +VM_PREFIX* tb = NULL; +bool pass = true; + +double sc_time_stamp() { + return 0; +} + +int main() { + Verilated::debug(0); + tb = new VM_PREFIX ("tb"); + + // Just a constructor test + bool pass = true; + + if (pass) { + VL_PRINTF("*-* All Finished *-*\n"); + } else { + vl_fatal(__FILE__,__LINE__,"top", "Unexpected results from test\n"); + } + return 0; +} diff --git a/test_regress/t/t_mem_multi_io3.v b/test_regress/t/t_mem_multi_io3.v new file mode 100644 index 000000000..e2d82667f --- /dev/null +++ b/test_regress/t/t_mem_multi_io3.v @@ -0,0 +1,52 @@ +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2013. + +module t + ( + input logic clk, + input logic daten, + input logic [8:0] datval, + output logic signed [3:0][3:0][35:0] datao + ); + + logic signed [3:0][3:0][3:0][8:0] datat; + + genvar i; + generate + for (i=0; i<4; i++)begin + testio dut(.clk(clk), .arr3d_in(datat[i]), .arr2d_out(datao[i])); + end + endgenerate + + genvar j; + generate + for (i=0; i<4; i++) begin + for (j=0; j<4; j++) begin + always_comb datat[i][j][0] = daten ? 9'h0 : datval; + always_comb datat[i][j][1] = daten ? 9'h1 : datval; + always_comb datat[i][j][2] = daten ? 9'h2 : datval; + always_comb datat[i][j][3] = daten ? 9'h3 : datval; + end + end + endgenerate +endmodule + +module testio + ( + input clk, + input logic signed [3:0] [3:0] [8:0] arr3d_in, + output logic signed [3:0] [35:0] arr2d_out + ); + logic signed [3:0] [35:0] ar2d_out_pre; + + always_comb ar2d_out_pre[0][35:0] = {arr3d_in[0][0][8:0], arr3d_in[0][1][8:0], arr3d_in[0][2][8:0], arr3d_in[0][3][8:0]}; + always_comb ar2d_out_pre[0][35:0] = {arr3d_in[0][0][8:0], arr3d_in[0][1][8:0], arr3d_in[0][2][8:0], arr3d_in[0][3][8:0]}; + always_comb ar2d_out_pre[0][35:0] = {arr3d_in[0][0][8:0], arr3d_in[0][1][8:0], arr3d_in[0][2][8:0], arr3d_in[0][3][8:0]}; + always_comb ar2d_out_pre[0][35:0] = {arr3d_in[0][0][8:0], arr3d_in[0][1][8:0], arr3d_in[0][2][8:0], arr3d_in[0][3][8:0]}; + + always_ff @(posedge clk) begin + if (clk) + arr2d_out <= ar2d_out_pre; + end + +endmodule diff --git a/test_regress/t/t_mem_multi_io3_cc.pl b/test_regress/t/t_mem_multi_io3_cc.pl new file mode 100755 index 000000000..d9a9e9be1 --- /dev/null +++ b/test_regress/t/t_mem_multi_io3_cc.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_mem_multi_io3.v"); + +$Self->{vlt} or $Self->skip("Verilator only test"); + +compile ( + make_top_shell => 0, + make_main => 0, + verilator_flags2 => ["--exe $Self->{t_dir}/t_mem_multi_io3.cpp -Oi"], + ); + +ok(1); +1; diff --git a/test_regress/t/t_mem_multi_io3_sc.pl b/test_regress/t/t_mem_multi_io3_sc.pl new file mode 100755 index 000000000..5d54f4f4e --- /dev/null +++ b/test_regress/t/t_mem_multi_io3_sc.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_mem_multi_io3.v"); + +$Self->{vlt} or $Self->skip("Verilator only test"); + +compile ( + make_top_shell => 0, + make_main => 0, + verilator_flags2 => ["--exe $Self->{t_dir}/t_mem_multi_io3.cpp --sc -Oi"], + ); + +ok(1); +1;