dfianthdl / dfhdl Goto Github PK
View Code? Open in Web Editor NEWDFiant HDL (DFHDL): A Dataflow Hardware Descripition Language
Home Page: https://dfianthdl.github.io/
License: GNU Lesser General Public License v3.0
DFiant HDL (DFHDL): A Dataflow Hardware Descripition Language
Home Page: https://dfianthdl.github.io/
License: GNU Lesser General Public License v3.0
Trying to index and assign to a Bits(1) fails with the error below.
import dfhdl.*
class Width0Issue(val width : Int <> CONST) extends RTDesign:
val d = Bit <> IN
val a = Bits(width) <> VAR
a(0) := d // works only when width > 1
// a := d // works like this when width = 1
@main def main =
Width0Issue(1).compile
Width0Issue(2).compile // works
DFiant HDL elaboration error!
Position: ~/Documents/DFHDL_examples/Issues.scala:6:5 - 6:9
Hierarchy: Width0Issue
Operation: `apply`
Message: Unsigned value width must be positive, but found: 0
val clkCfg1 = ClkCfg(ClkCfg.Edge.Rising)
val rstCfg1 = RstCfg(RstCfg.Mode.Sync, RstCfg.Active.High)
val rtcfg = RTDomainCfg(clkCfg1, rstCfg1)
class INV() extends RTDesign:
val a = Bit <> IN
val c = Bit <> VAR.REG init 0
val b = Bit <> OUT
c.din := a
b := !a && c
class ClockRstConnection() extends RTDesign(rtcfg):
val a = Bit <> IN
val b = Bit <> OUT
val inv0 = new INV()
inv0.a <> a
inv0.b <> b
@main def main =
ClockRstConnection().compile
`default_nettype none
`timescale 1ns/1ps
`include "ClockRstConnection_defs.sv"
module ClockRstConnection(
input wire logic clk,
input wire logic rst,
input wire logic a,
output logic b
);
logic inv0_clk; // declared but never assigned
logic inv0_rst;
logic inv0_a;
logic inv0_b;
INV inv0(
.clk /*<--*/ (inv0_clk),
.rst /*<--*/ (inv0_rst),
.a /*<--*/ (inv0_a),
.b /*-->*/ (inv0_b)
);
assign inv0_a = a;
assign b = inv0_b;
endmodule
>> is translated to >> in the case of SInt, but it should be >>>.
import dfhdl._
class VerilogSRA() extends RTDesign:
val a = SInt(10) <> IN
val b = SInt(10) <> VAR
b := a >> 1
@main def main =
VerilogSRA().compile
module VerilogSRA(
input wire logic signed [9:0] a
);
logic signed [9:0] b;
always @(*)
begin
b = a >> 1; \\ this is a logical right shift, which doesn't keep the sign bit
end
endmodule
Clock and reset are missing in the generated code, when the top level class has both no REG and no explicit RTDomainCfg (that is, only compiler config is given). Basically, when the top level is combinational.
class INV() extends RTDesign():
val a = Bit <> IN
val c = Bit <> VAR.REG init 0
val b = Bit <> OUT
c.din := a
b := !a && c
class NoCfgClockRst() extends RTDesign(): // if RTDesign(cfg) it works fine
val a = Bit <> IN
val b = Bit <> OUT // with OUT.REG it works
val inv0 = new INV()
inv0.a <> a
inv0.b <> b
given options.CompilerOptions.DefaultClkCfg = ClkCfg(ClkCfg.Edge.Rising)
given options.CompilerOptions.DefaultRstCfg = RstCfg(RstCfg.Mode.Sync, RstCfg.Active.Low)
@main def main =
NoCfgClockRst().compile
`default_nettype none
`timescale 1ns/1ps
`include "NoCfgClockRst_defs.sv"
module INV(
input wire logic a,
output logic b
);
logic c;
logic c_din;
always @(*)
begin
c_din = c;
c_din = a;
b = (!a) & c;
end
endmodule
`default_nettype none
`timescale 1ns/1ps
`include "NoCfgClockRst_defs.sv"
module NoCfgClockRst(
input wire logic a,
output logic b
);
logic inv0_a;
logic inv0_b;
INV inv0(
.a /*<--*/ (inv0_a),
.b /*-->*/ (inv0_b)
);
assign inv0_a = a;
assign b = inv0_b;
endmodule
The functions to_bool and to_sl don't exist in the generated VHDL package.
//> using scala 3.4.0
//> using dep io.github.dfianthdl::dfhdl::0.4.3+12-a64c002c-SNAPSHOT
//> using plugin io.github.dfianthdl:::dfhdl-plugin:0.4.3+12-a64c002c-SNAPSHOT
//> using option -deprecation -language:implicitConversions
import dfhdl.*
class TypeConvertIssue() extends RTDesign:
val a = Bit <> IN
val b = Bit <> IN
val c = UInt(8) <> IN
val d = Bit <> OUT
val e = Bit <> OUT
d := 0
if (c < 3 && b)
d := 1
e := 0
if (b && c < 3)
e := 1
@main def main =
TypeConvertIssue().compile
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.TypeConvertIssue_pkg.all;
entity TypeConvertIssue is
port (
a : in std_logic;
b : in std_logic;
c : in unsigned(7 downto 0);
d : out std_logic;
e : out std_logic
);
end TypeConvertIssue;
architecture TypeConvertIssue_arch of TypeConvertIssue is
begin
process (all)
begin
d <= '0';
if (c < 8d"3") and to_bool(b) then d <= '1'; -- uses to_bool which does not exist
end if;
e <= '0';
if b and to_sl(c < 8d"3") then e <= '1'; -- uses to_sl which does not exist
end if;
end process;
end TypeConvertIssue_arch;
Generated VHDL uses the function to_slv to convert b(0), but the function does not exist for std_logic.
The following function is needed
-- in package header
function to_slv(A : std_logic) return std_logic_vector;
-- in package body
function to_slv(A : std_logic) return std_logic_vector is
begin
if A = '1' then
return "1";
else
return "0";
end if;
end;
class StdLogicConvIssue() extends RTDesign:
val a = Bits(10) <> IN
val e = Bits(10) <> OUT
e := (a(0), a(3), b"0", false.bit, b"000000")
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.StdLogicConvIssue_pkg.all;
entity StdLogicConvIssue is
port (
a : in std_logic_vector(9 downto 0);
e : out std_logic_vector(9 downto 0)
);
end StdLogicConvIssue;
architecture StdLogicConvIssue_arch of StdLogicConvIssue is
begin
process (all)
begin
e <= to_slv(a(0)) & to_slv(a(3)) & "0" & "0" & 6x"00"; -- problem here
end process;
end StdLogicConvIssue_arch;
Structs that are used in the port declaration are declared in the package, whereas structs used internally are declared in the architecture, which leads to double struct declaration.
case class InStruct (
a : Bit <> VAL,
b : Bit <> VAL
) extends Struct
class DoubleStructDecl() extends RTDesign():
val sin = InStruct <> IN
val svar = InStruct <> VAR
svar := sin
given options.CompilerOptions.Backend = backends.vhdl.v2008
@main def main =
DoubleStructDecl().compile
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.DoubleStructDecl_pkg.all;
entity DoubleStructDecl is
port (
clk : in std_logic;
rst : in std_logic;
sin : in t_struct_InStruct -- declared in the package
);
end DoubleStructDecl;
architecture DoubleStructDecl_arch of DoubleStructDecl is
type t_struct_InStruct is record -- redeclared here
a : std_logic;
b : std_logic;
end record;
signal svar : t_struct_InStruct;
begin
process (all)
begin
svar <= sin;
end process;
end DoubleStructDecl_arch;
Same error message as #116 and seems related to if statements again. The error occurs for both VHDL and Verilog.
import dfhdl.*
class DictControl(
val fetch_count : Int <> CONST, // set to 2
val dict_entry_size : Int = 20
) extends RTDesign:
val dict_in = Bits(fetch_count * dict_entry_size) <> IN
val matching = Bits(fetch_count) <> VAR
val addr_r = Bits(12) <> VAR.REG init all(0)
val idx_r = Bits(12) <> VAR.REG init all(0)
val sym_r = Bits(8) <> VAR.REG init all(0)
val entry_count = UInt(12) <> VAR.REG init 0
entry_count.din := 0
sym_r.din := b"8'0"
idx_r.din := b"12'0"
addr_r.din := b"12'0"
for (i <- 0 until fetch_count.toScalaInt)
if ((dict_in(dict_entry_size * (i+1) - 1, dict_entry_size * i) == (idx_r, sym_r)) && (addr_r + i < entry_count - 1))
matching(i) := 1
@main def main =
DictControl(fetch_count = 2).compile
Exception in thread "main" java.util.NoSuchElementException: head of empty list
at scala.collection.immutable.Nil$.head(List.scala:662)
at scala.collection.immutable.Nil$.head(List.scala:661)
at dfhdl.compiler.ir.DB.OMLGen(DB.scala:137)
at dfhdl.compiler.ir.DB.blockMemberList$lzyINIT1(DB.scala:221)
at dfhdl.compiler.ir.DB.blockMemberList(DB.scala:221)
at dfhdl.compiler.stages.UniqueNames.transform(UniqueNames.scala:72)
at dfhdl.compiler.stages.StageRunner.runSingleStage(StageRunner.scala:22)
at dfhdl.compiler.stages.StageRunner.dfhdl$compiler$stages$StageRunner$$run(StageRunner.scala:43)
at dfhdl.compiler.stages.StageRunner$.run(StageRunner.scala:55)
at dfhdl.backends$vhdl.printer(backends.scala:27)
at dfhdl.compiler.stages.BackendCompiler.compile(BackendCompiler.scala:19)
at dfhdl.compiler.stages.BackendCompiler.compile$(BackendCompiler.scala:8)
at dfhdl.backends$vhdl.compile(backends.scala:23)
at dfhdl.compiler.stages.StagedDesign$.compile(StagedDesign.scala:13)
at dfhdl.ops$package$.compile(ops.scala:10)
at project$package$.main(project.scala:39)
at main.main(project.scala:27)
The generated code of the entity uses the types t_array_elem0 / t_array_elem1/t_array_elem2, which do not exist in the associated package.
I am also wondering what multidimensional arrays would look like.
Either
type <name> is array (natural range <>, natural range <>, ...) of <element_type>
and indexed as e.g. arr(0, 0, ...)
or
type <name1> is array (natural range <>) of <element_type>
type <name2> is array (natural range <>) of <name1>
and indexed as e.g. arr(0)(0)...
//> using scala 3.4.0
//> using dep io.github.dfianthdl::dfhdl::0.4.6
//> using plugin io.github.dfianthdl:::dfhdl-plugin:0.4.6
//> using option -deprecation -language:implicitConversions
import dfhdl.*
class ArrayIssue() extends RTDesign:
val a = Bit <> IN
val b = Bit X 6 <> VAR
val c = Bit X 5 X 4 <> VAR
val d = Bits(4) X 3 X 2 <> VAR
b(0) := a
c(0)(0) := a
d(0)(0)(0) := a
given options.CompilerOptions.PrintGenFiles = true
given options.CompilerOptions.Backend = backends.vhdl
@main def main =
ArrayIssue().compile
If c and d are indexed as in the VHDL code it would require the latter variant of multidimensional arrays above.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.ArrayIssue_pkg.all;
entity ArrayIssue is
port (
a : in std_logic
);
end ArrayIssue;
architecture ArrayIssue_arch of ArrayIssue is
signal b : t_array_elem0(0 to 6 - 1);
signal c : t_array_elem1(0 to 4 - 1);
signal d : t_array_elem2(0 to 2 - 1);
begin
process (all)
begin
b(0) <= a;
c(0)(0) <= a;
d(0)(0)(0) <= a;
end process;
end ArrayIssue_arch;
Shifts are incorrectly converted to VHDL incorrectly in some cases. For a bitvector right shift sla is used instead of srl and for signed right shift the generated signed_sra function converts the signed value to unsigned, which leads to incorrect behavior for negative numbers. Shifts with unsigned (UInt) seem correct.
//> using scala 3.4.0
//> using dep io.github.dfianthdl::dfhdl::0.4.3+12-a64c002c-SNAPSHOT
//> using plugin io.github.dfianthdl:::dfhdl-plugin:0.4.3+12-a64c002c-SNAPSHOT
//> using option -deprecation -language:implicitConversions
import dfhdl.*
class ShiftIssue() extends RTDesign:
val bitvec = Bits(10) <> VAR
val bitvec2 = Bits(10) <> OUT
val bitvec3 = Bits(10) <> VAR
val signed1 = SInt(10) <> VAR
val signed2 = SInt(10) <> OUT
val signed3 = SInt(10) <> OUT
val unsigned1 = UInt(10) <> VAR
val unsigned2 = UInt(10) <> OUT
val unsigned3 = UInt(10) <> OUT
bitvec2 := bitvec >> 1 // not ok, uses sla instead of srl
bitvec3 := bitvec << 1 // ok
signed2 := signed1 >> 1 // not ok, converts value to unsigned before applying sra
signed3 := signed1 << 1 // ok
unsigned2 := unsigned1 >> 1
unsigned3 := unsigned1 << 1
given options.CompilerOptions.PrintGenFiles = true
given options.CompilerOptions.Backend = backends.vhdl
@main def main =
ShiftIssue().compile
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.ShiftIssue_pkg.all;
entity ShiftIssue is
port (
bitvec2 : out std_logic_vector(9 downto 0);
signed2 : out signed(9 downto 0);
signed3 : out signed(9 downto 0);
unsigned2 : out unsigned(9 downto 0);
unsigned3 : out unsigned(9 downto 0)
);
end ShiftIssue;
architecture ShiftIssue_arch of ShiftIssue is
signal bitvec : std_logic_vector(9 downto 0);
signal bitvec3 : std_logic_vector(9 downto 0);
signal signed1 : signed(9 downto 0);
signal unsigned1 : unsigned(9 downto 0);
begin
process (all)
begin
bitvec2 <= slv_srl(bitvec, 4d"1");
bitvec3 <= slv_sll(bitvec, 4d"1");
signed2 <= signed_sra(signed1, 4d"1");
signed3 <= signed1 sla 1;
unsigned2 <= unsigned1 srl 1;
unsigned3 <= unsigned1 sll 1;
end process;
end ShiftIssue_arch;
-- only relevant parts
function slv_sll(slv : std_logic_vector; num_shifts : unsigned) return std_logic_vector is
begin
return to_slv(unsigned(slv) sll to_integer(num_shifts));
end;
function slv_srl(slv : std_logic_vector; num_shifts : unsigned) return std_logic_vector is
begin
return to_slv(unsigned(slv) sla to_integer(num_shifts)); -- uses sla
end;
function signed_sra(A : signed; num_shifts : unsigned) return signed is
begin
return signed(unsigned(A) sra to_integer(num_shifts)); -- converted to unsigned
end;
end package body ShiftIssue_pkg;
import dfhdl._
case class EmbeddedArray (
a : Bits[8]X(3) <> VAL
) extends Struct
class StructArrayIssue() extends RTDesign:
val a = Bit <> IN
val e = EmbeddedArray <> VAR
e.a(0)(0) := a
given options.CompilerOptions.Backend = backends.vhdl.v2008
@main def main =
StructArrayIssue().compile
Exception in thread "main" java.lang.IllegalArgumentException: Unsupported member for this RTPrinter.
at dfhdl.compiler.stages.vhdl.VHDLPrinter.unsupported(VHDLPrinter.scala:17)
at dfhdl.compiler.stages.vhdl.VHDLValPrinter.csBitsToType(VHDLValPrinter.scala:116)
at dfhdl.compiler.stages.vhdl.VHDLValPrinter.csBitsToType$(VHDLValPrinter.scala:8)
at dfhdl.compiler.stages.vhdl.VHDLPrinter.csBitsToType(VHDLPrinter.scala:8)
at dfhdl.compiler.stages.vhdl.VHDLTypePrinter.$anonfun$5(VHDLTypePrinter.scala:156)
at scala.collection.StrictOptimizedIterableOps.map(StrictOptimizedIterableOps.scala:100)
at scala.collection.StrictOptimizedIterableOps.map$(StrictOptimizedIterableOps.scala:87)
at scala.collection.immutable.ListMap.map(ListMap.scala:43)
at dfhdl.compiler.stages.vhdl.VHDLTypePrinter.csDFStructConvFuncsBody(VHDLTypePrinter.scala:156)
at dfhdl.compiler.stages.vhdl.VHDLTypePrinter.csDFStructConvFuncsBody$(VHDLTypePrinter.scala:10)
at dfhdl.compiler.stages.vhdl.VHDLPrinter.csDFStructConvFuncsBody(VHDLPrinter.scala:8)
at dfhdl.compiler.stages.vhdl.VHDLOwnerPrinter$$anon$3.applyOrElse(VHDLOwnerPrinter.scala:58)
at dfhdl.compiler.stages.vhdl.VHDLOwnerPrinter$$anon$3.applyOrElse(VHDLOwnerPrinter.scala:58)
at scala.collection.Iterator$$anon$7.hasNext(Iterator.scala:525)
at scala.collection.IterableOnceOps.addString(IterableOnce.scala:1245)
at scala.collection.IterableOnceOps.addString$(IterableOnce.scala:1241)
at scala.collection.AbstractIterable.addString(Iterable.scala:933)
at scala.collection.IterableOnceOps.mkString(IterableOnce.scala:1191)
at scala.collection.IterableOnceOps.mkString$(IterableOnce.scala:1189)
at scala.collection.AbstractIterable.mkString(Iterable.scala:933)
at scala.collection.IterableOnceOps.mkString(IterableOnce.scala:1204)
at scala.collection.IterableOnceOps.mkString$(IterableOnce.scala:1204)
at scala.collection.AbstractIterable.mkString(Iterable.scala:933)
at dfhdl.compiler.stages.vhdl.VHDLOwnerPrinter.csArchitectureDcl(VHDLOwnerPrinter.scala:59)
at dfhdl.compiler.stages.vhdl.VHDLOwnerPrinter.csArchitectureDcl$(VHDLOwnerPrinter.scala:10)
at dfhdl.compiler.stages.vhdl.VHDLPrinter.csArchitectureDcl(VHDLPrinter.scala:8)
at dfhdl.compiler.stages.vhdl.VHDLOwnerPrinter.csDFDesignBlockDcl(VHDLOwnerPrinter.scala:89)
at dfhdl.compiler.stages.vhdl.VHDLOwnerPrinter.csDFDesignBlockDcl$(VHDLOwnerPrinter.scala:10)
at dfhdl.compiler.stages.vhdl.VHDLPrinter.csDFDesignBlockDcl(VHDLPrinter.scala:8)
at dfhdl.compiler.printing.Printer.csFile(Printer.scala:150)
at dfhdl.compiler.printing.Printer.csFile$(Printer.scala:19)
at dfhdl.compiler.stages.vhdl.VHDLPrinter.csFile(VHDLPrinter.scala:8)
at dfhdl.compiler.printing.Printer.$anonfun$1(Printer.scala:170)
at scala.collection.immutable.List.map(List.scala:246)
at dfhdl.compiler.printing.Printer.printedDB(Printer.scala:172)
at dfhdl.compiler.printing.Printer.printedDB$(Printer.scala:19)
at dfhdl.compiler.stages.vhdl.VHDLPrinter.printedDB(VHDLPrinter.scala:8)
at dfhdl.compiler.stages.BackendCompiler.compile(BackendCompiler.scala:19)
at dfhdl.compiler.stages.BackendCompiler.compile$(BackendCompiler.scala:8)
at dfhdl.backends$vhdl.compile(backends.scala:23)
at dfhdl.compiler.stages.StagedDesign$.compile(StagedDesign.scala:13)
at dfhdl.ops$package$.compile(ops.scala:10)
at project$package$.main(project.scala:51)
at main.main(project.scala:27)
Arrays require integers for indexing, but the generated VHDL uses unsigned (for non constant values). The function to_integer() should be used.
import dfhdl._
class IntegerIndexingIssue() extends RTDesign:
val a = Bits(4) <> IN
val b = Bits(12) X 16 <> VAR.REG init all(all(0))
val c = Bits(12) <> OUT
c := b(a)
given options.CompilerOptions.PrintGenFiles = true
given options.CompilerOptions.Backend = backends.vhdl.v2008
@main def main =
IntegerIndexingIssue().compile
architecture IntegerIndexingIssue_arch of IntegerIndexingIssue is
type t_vecX1_std_logic_vector is array (natural range <>) of std_logic_vector;
signal b : t_vecX1_std_logic_vector(0 to 16 - 1)(11 downto 0);
signal b_din : t_vecX1_std_logic_vector(0 to 16 - 1)(11 downto 0);
begin
process (all)
begin
b_din <= b;
c <= b(unsigned(a)); -- to_integer(unsigned(a));
end process;
process (clk)
begin
if rising_edge(clk) then
if rst = '1' then b <= (0 to 16-1 => x"000");
else b <= b_din;
end if;
end if;
end process;
end IntegerIndexingIssue_arch;
Trying to use a field of a struct in a level other than the outermost one of a nested if yields an error. It works fine otherwise and also works when assigning the field to a variable and using that variable in an inner level.
//> using scala 3.4.0
//> using lib io.github.dfianthdl::dfhdl::0.4.3
//> using plugin io.github.dfianthdl:::dfhdl-plugin:0.4.3
//> using option -deprecation -language:implicitConversions
import dfhdl.* //import all the DFHDL goodness
case class Test (
a : Bit <> VAL,
b : Bit <> VAL
) extends Struct
class GlobCounter (val width: Int <> CONST) extends RTDesign:
val req = Bit <> IN
val req2 = Bit <> IN
val t = Test <> IN
val t_b = Bit <> VAR
t_b := t.b
val t_int = Test <> VAR
t_int := t
val cnt = UInt(width) <> OUT.REG init 0
// doesn't work
if (t.a) {
if (t.b) {
cnt.din := cnt + 1
}
}
// doesn't work
// if (req) {
// if (t.b) {
// cnt.din := cnt + 1
// }
// }
// no if nesting, works
// if (t.a && t.b) {
// cnt.din := cnt + 1
// }
// works
// if (t.a) {
// if (t_b) {
// cnt.din := cnt + 1
// }
// }
// doesn't work
// if (t_int.a) {
// if (t_int.b) {
// cnt.din := cnt + 1
// }
// }
// works
// if (req) {
// if (req2) {
// cnt.din := cnt + 1
// }
// }
////////////////////////////////////////////////////////////////////////////////////////////////
// DFHDL Compiler Options: //
////////////////////////////////////////////////////////////////////////////////////////////////
// Enables printing the generated chosen backend code:
given options.CompilerOptions.PrintGenFiles = true
// Uncomment to select vhdl compilation (default is verilog):
// given options.CompilerOptions.Backend = backends.vhdl
// Uncomment to enable printing design code before compilation (after elaboration):
// given options.CompilerOptions.PrintDesignCodeBefore = true
// Uncomment to enable printing design code after compilation:
// given options.CompilerOptions.PrintDesignCodeAfter = true
// Uncomment to set different clock and reset configurations:
// given options.CompilerOptions.DefaultClkCfg = ClkCfg(ClkCfg.Edge.Rising)
// given options.CompilerOptions.DefaultRstCfg = RstCfg(RstCfg.Mode.Async, RstCfg.Active.Low)
////////////////////////////////////////////////////////////////////////////////////////////////
//The entry point to your compilation program starts here
@main def main = GlobCounter(64).compile
When run with scala-cli this is the output
[warn] ./GlobCounter.scala:2:11
[warn] Using 'lib' is deprecated, use 'dep' instead
[warn] //> using lib io.github.dfianthdl::dfhdl::0.4.3
[warn] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Compiling project (Scala 3.4.0, JVM (17))
Compiled project (Scala 3.4.0, JVM (17))
Exception in thread "main" java.util.NoSuchElementException: head of empty list
at scala.collection.immutable.Nil$.head(List.scala:662)
at scala.collection.immutable.Nil$.head(List.scala:661)
at dfhdl.compiler.ir.DB.OMLGen(DB.scala:137)
at dfhdl.compiler.ir.DB.ownerMemberList$lzyINIT1(DB.scala:165)
at dfhdl.compiler.ir.DB.ownerMemberList(DB.scala:165)
at dfhdl.compiler.ir.DB.ownerMemberTable$lzyINIT1(DB.scala:190)
at dfhdl.compiler.ir.DB.ownerMemberTable(DB.scala:190)
at dfhdl.compiler.ir.DB.getMembersOf(DB.scala:181)
at dfhdl.compiler.analysis.DFOwnerAnalysis$package$.members(DFOwnerAnalysis.scala:8)
at dfhdl.compiler.stages.VHDLProcToVerilog$.$anonfun$1(VHDLProcToVerilog.scala:33)
at scala.collection.immutable.List.flatMap(List.scala:293)
at dfhdl.compiler.stages.VHDLProcToVerilog$.transform(VHDLProcToVerilog.scala:82)
at dfhdl.compiler.stages.StageRunner.runSingleStage(StageRunner.scala:22)
at dfhdl.compiler.stages.StageRunner.dfhdl$compiler$stages$StageRunner$$run(StageRunner.scala:43)
at dfhdl.compiler.stages.StageRunner$.run(StageRunner.scala:55)
at dfhdl.backends$verilog.printer(backends.scala:15)
at dfhdl.compiler.stages.BackendCompiler.compile(BackendCompiler.scala:19)
at dfhdl.compiler.stages.BackendCompiler.compile$(BackendCompiler.scala:8)
at dfhdl.backends$verilog.compile(backends.scala:11)
at dfhdl.compiler.stages.StagedDesign$.compile(StagedDesign.scala:13)
at dfhdl.ops$package$.compile(ops.scala:10)
at GlobCounter$package$.main(GlobCounter.scala:82)
at main.main(GlobCounter.scala:82)
In std_logic_vector to struct conversion functions, bitWidth(A)
is used, where A is the input and a std_logic_vector, but the function doesn't exist. The function to_sl()
is used on a sliced std_logic_vector, but only exists for bools. This happens for Bit
/std_logic
in a struct. Either a function like to_sl(A : std_logic_vector(0 downto 0))
(1) is needed or alternatively A(lo)
is assigned instead of to_sl(A(hi downto lo))
.
import dfhdl._
case class Atest (
a : Bits[10] <> VAL,
b : UInt[10] <> VAL,
c : SInt[10] <> VAL,
d : Bit <> VAL
) extends Struct;
class StructConvIssue() extends RTDesign:
val a = Bits(10) <> IN
val Astruct = Atest <> VAR
Astruct.a := a
Astruct.b := a
Astruct.c := a.sint
@main def main =
StructConvIssue().compile
-- pkg not shown
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.StructConvIssue_pkg.all;
entity StructConvIssue is
port (
a : in std_logic_vector(9 downto 0)
);
end StructConvIssue;
architecture StructConvIssue_arch of StructConvIssue is
type t_struct_Atest is record
a : std_logic_vector(9 downto 0);
b : unsigned(9 downto 0);
c : signed(9 downto 0);
d : std_logic;
end record;
function bitWidth(A : t_struct_Atest) return integer is
variable len : integer;
begin
len := 0;
len := len + A.a'length;
len := len + A.b'length;
len := len + A.c'length;
len := len + 1;
return len;
end;
function to_slv(A : t_struct_Atest) return std_logic_vector is
variable hi : integer;
variable lo : integer;
variable ret : std_logic_vector(bitWidth(A) - 1 downto 0);
begin
lo := bitWidth(A);
hi := lo - 1; lo := hi - A.a'length + 1; ret(hi downto lo) := A.a;
hi := lo - 1; lo := hi - A.b'length + 1; ret(hi downto lo) := to_slv(A.b);
hi := lo - 1; lo := hi - A.c'length + 1; ret(hi downto lo) := to_slv(A.c);
hi := lo - 1; lo := hi - 1 + 1; ret(hi downto lo) := to_slv(A.d);
return ret;
end;
function to_t_struct_Atest(A : std_logic_vector) return t_struct_Atest is
variable hi : integer;
variable lo : integer;
variable ret : t_struct_Atest;
begin
lo := bitWidth(A); -- A is a std_logic_vector, should be 'length instead?
hi := lo - 1; lo := hi - ret.a'length + 1; ret.a := A(hi downto lo);
hi := lo - 1; lo := hi - ret.b'length + 1; ret.b := unsigned(A(hi downto lo));
hi := lo - 1; lo := hi - ret.c'length + 1; ret.c := signed(A(hi downto lo));
hi := lo - 1; lo := hi - 1 + 1; ret.d := to_sl(A(hi downto lo)); -- to_sl used on a sliced std_logic_vector which has width 1
return ret;
end;
signal Astruct : t_struct_Atest;
begin
process (all)
begin
Astruct.a <= a;
Astruct.b <= unsigned(a);
Astruct.c <= signed(a);
end process;
end StructConvIssue_arch;
(1)
-- pkg header
function to_sl(A : std_logic_vector(0 downto 0)) return std_logic;
-- pkg body
function to_sl(A : std_logic_vector(0 downto 0)) return std_logic
is
begin
if (A = "1") then
return '1';
else
return '0';
end if;
end;
Assigning .prev / .prev(1) to an OUT gives the expected result, but assigning it to a VAR doesn't. In the below example, the Verilog code has a being assigned to c directly instead of a_reg1. For higher orders, it works as expected, as shown by e.
import dfhdl.*
class FirstDF() extends DFDesign:
val a = Bit <> IN init 0
val c = Bit <> VAR
val e = Bit <> VAR
c := a.prev(1)
e := a.prev(2)
val d = Bit <> OUT init 0
d := a.prev
@main def main =
FirstDF().compile
module FirstDF(
input wire logic clk,
input wire logic rst,
input wire logic a,
output logic d
);
logic c;
logic e;
logic a_reg1;
logic a_reg2;
always @(*)
begin
e = a_reg2;
d = a_reg1;
end
always @(posedge clk)
begin
if (rst == 1'b1) begin
a_reg1 <= 1'b0;
a_reg2 <= 1'b0;
c <= 1'b0;
end
else begin
a_reg1 <= a;
a_reg2 <= a_reg1;
c <= a;
end
end
endmodule
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.