nic30 / hwt Goto Github PK
View Code? Open in Web Editor NEWVHDL/Verilog/SystemC code generator, simulator API written in python/c++
License: MIT License
VHDL/Verilog/SystemC code generator, simulator API written in python/c++
License: MIT License
Hi Nic30:
Is it possible to instantiate a VHDL or Verilog IP as a black-box component like Spinalhdl? Thanks.
HDL/RTL simulator should not be part of this library. It will be extracted to separate library.
Temporal repository for this library is https://github.com/Nic30/pycocotb.
Also the C++ Verilator simulator will be available.
Properties of the Verilator:
I am also working on simple simulation API which will make the writing of UVM like interface agents easy.
The state is that I do have working prototype but I do not have to submit patches to Verilator.
I do expect that library will be finished after December or in February.
BitVal/HBoolVal/HIntVal ... instances does not require type definition and validity mask if it can be derived from python value
HArrayVal/HSliceVal ... instances does not require specification for all items if they are same and they do not require type defnition if it can be expressed in python
Currently If-then-else and other condition containers are constructed in HDL rendering phase.
This means every Assignment instance has list of it's conditions and condition containers are resolved from them.
This makes thing complicated and slow.
This has to be removed and replaced with condition tree with hierarchy represented by real objects.
Every object has to have reference on it's parent and has to have specified where it is in the parent.
Every RtlSignal then will have only top condition container in it's drivers or endpoints.
They actually exists https://github.com/Nic30/hwt/blob/master/hwt/simulator/utils.py#L8,
but there is no tutorial about it.
Axi_basic_slave_140321357064568 : COMPONENT Axi_basic_slave
GENERIC MAP (
C_S_AXI_ADDR_WIDTH => 4,
C_S_AXI_DATA_WIDTH => 32
...
class AxiLiteSlaveContainer(Unit):
ADDR_WIDTH = Param(8)
DATA_WIDTH = Param(8)
...
slv.C_S_AXI_ADDR_WIDTH.inherit(ADDR_WIDTH)
slv.C_S_AXI_DATA_WIDTH.inherit(DATA_WIDTH)
If the exception is raised somewhere deep inside of operator function it usually means ~5 function calls and user can get lost easily. It also does not look like an error in user code.
In order to use component from HDL it is usually required to pre-generate at least several component variants and select from them based on used parameter configuration in HDL.
Extract interface arrays as separate library, because it is complicated and users does not understand the difference between
It is useful feature but it is too complicated for base hwt library. Learning curve of uses and intuitive usage has priority.
This also means the removal of SimProxies for this interfaces. And magic indexation overriding, array items cache and it's usage for interfaces.
~ 2018-06-30
ENTITY AxiLiteSlaveContainer IS
GENERIC (
ADDR_WIDTH : INTEGER := 8;
DATA_WIDTH : INTEGER := 8
);
PORT (axi_ar_addr : IN STD_LOGIC_VECTOR(31 DOWNTO 0);
axi_aw_addr : IN STD_LOGIC_VECTOR(31 DOWNTO 0);
axi_r_data : OUT STD_LOGIC_VECTOR(63 DOWNTO 0);
...
the param from interface declaration is used instead
To simplify parallel build of HLS components it is required to know direction of all interfaces on boundaries of components.
Also platform definition which is passed to toRtl() function should contains predefined pool of worker processes for HLS engines.
Also interface direction resolution should be extracted to https://github.com/Nic30/hwtHdlParsers
I'm getting the error
File "/home/ben/Code/hwt/hwt/hdl/ifContainter.py", line 193, in _discover_sensitivity
assert self._sensitivity is None, self
AssertionError: If(a._eq(0x1),
intermed_next(0x1),
)
Uncaught exception. Entering post mortem debugging
Running 'cont' or 'step' will restart the program
> /home/ben/Code/hwt/hwt/hdl/ifContainter.py(193)_discover_sensitivity()
-> assert self._sensitivity is None, self
when running the following code:
from hwt.synthesizer.unit import Unit
from hwt.hdl.types.enum import HEnum
from hwt.hdl.types.bits import Bits
from hwt.code import If
from hwt.interfaces.std import Signal, VectSignal
from hwt.serializer.verilog.serializer import VerilogSerializer
class Minimal(Unit):
def _declr(self):
self.clk = Signal()
self.a = VectSignal(2)
self.b = VectSignal(2)
self.c = Signal()._m()
def _impl(self):
one = self._sig('one', Bits(1))
intermed = self._reg('intermed', Bits(1))
one(1)
self.c(intermed)
If(one._eq(1), (
If(self.a._eq(1), (
intermed(1),
)),
If(self.b._eq(1), (
intermed(0),
)),
If(self.b._eq(2), (
intermed(1),
)),
))
''
def main():
from hwt.synthesizer.utils import toRtl
u = Minimal()
contents = toRtl(u, serializer=VerilogSerializer)
filename = 'minimal.v'
with open(filename, 'w') as f:
f.write(contents)
if __name__ == '__main__':
main()
For the following code:
import math
from hwt.synthesizer.param import Param
from hwt.synthesizer.unit import Unit
from hwt.hdl.types.bits import Bits
from hwt.interfaces.std import Signal
from hwt.hdl.types.array import HArray
class LUTSin(Unit):
def _declr(self):
self.idx = Signal(Bits(4))
self.data = Signal(Bits(8))._m()
def _impl(self):
lut = self._sig(name="lut", dtype=HArray(Bits(8,signed=True),16),
def_val=[int(math.sin(i*math.pi*2/16)*127+0.5) for i in range(16)])
self.data(lut[self.idx])
if __name__ == "__main__":
from hwt.synthesizer.utils import to_rtl_str
from hwt.serializer.vhdl import Vhdl2008Serializer
from hwt.serializer.verilog import VerilogSerializer
print(to_rtl_str(LUTSin(), serializer_cls=Vhdl2008Serializer))
print(to_rtl_str(LUTSin(), serializer_cls=VerilogSerializer))
Output of VHDL serializer (Correct initialization):
LIBRARY IEEE;
USE IEEE.std_logic_1164.ALL;
USE IEEE.numeric_std.ALL;
ENTITY LUTSin IS
PORT(
data : OUT STD_LOGIC_VECTOR(7 DOWNTO 0);
idx : IN STD_LOGIC_VECTOR(3 DOWNTO 0)
);
END ENTITY;
ARCHITECTURE rtl OF LUTSin IS
TYPE arr_t_0 IS ARRAY (15 DOWNTO 0) OF SIGNED(7 DOWNTO 0);
CONSTANT lut : arr_t_0 := (
SIGNED'(X"00"),
SIGNED'(X"31"),
SIGNED'(X"5A"),
SIGNED'(X"75"),
SIGNED'(X"7F"),
SIGNED'(X"75"),
SIGNED'(X"5A"),
SIGNED'(X"31"),
SIGNED'(X"00"),
SIGNED'(X"-30"),
SIGNED'(X"-59"),
SIGNED'(X"-74"),
SIGNED'(X"-7E"),
SIGNED'(X"-74"),
SIGNED'(X"-59"),
SIGNED'(X"-30"));
BEGIN
assig_process_data: PROCESS(idx)
VARIABLE tmpCastExpr_0 : SIGNED(7 DOWNTO 0);
BEGIN
tmpCastExpr_0 := lut(TO_INTEGER(UNSIGNED(idx)));
data <= STD_LOGIC_VECTOR(tmpCastExpr_0);
END PROCESS;
END ARCHITECTURE;
Output of Verilog serializer (Incorrect initialization)
module LUTSin (
output reg[7:0] data,
input wire[3:0] idx
);
reg signed[7:0] lut[0:15];
always @(idx) begin: assig_process_data
data = $signed(lut[idx]);
end
initial begin
lut[0] = 0;
lut[1] = 1;
lut[2] = 2;
lut[3] = 3;
lut[4] = 4;
lut[5] = 5;
lut[6] = 6;
lut[7] = 7;
lut[8] = 8;
lut[9] = 9;
lut[10] = 10;
lut[11] = 11;
lut[12] = 12;
lut[13] = 13;
lut[14] = 14;
lut[15] = 15;
end
endmodule
Hi @Nic30,
I have the following piece of code (please ignreo the Flow stuff for now). HWT complains that valid has multiple drivers.
def _declr(self):
addClkRstn(self)
self.a = Flow()._m()
self.b = Flow()
def _impl(self):
data = self._reg(name="data", dtype=self.a.data._dtype)
valid = self._reg(name="valid", dtype=Bits(1))
valid(valid & ~self.a.fire())
If(self.b.fire(),
data(self.a.data),
valid(True))
self.a.data(data)
self.a.valid(valid)
What I want to describe the the verilog equivalent of
valid_a <= 0;
if(valid_b) begin
valid_a <= 1;
end
So essentially I am wondering if I can have a "last assigment wins" policy. I know this example is not so meaningful and you can easily get around it be using else clauses. This is more a conceptional question.
Is there some other channel to ask questions?
Add formal verification statement in same manner as constraint specification.
Hi, I am playing with the examples from the wiki. The second one (SimpleUnitWithParam) introduces parameters. However it seems that since a commit in 2021 this is somehow broken or the API has changed in a way that the example isnt working.
Instead of generating generic code where the verilog parameter / VHDL generic is used, hwt will just use the constant and emit an assertion if the parameter was indeed set to that constant. That is not very useful.
regards
Philip
rtlLvl/simpleRegister.py
IF ((rst = '1') AND (RISING_EDGE(clk))) THEN
val <= STD_LOGIC_VECTOR(TO_UNSIGNED(0, val'LENGTH));
END IF;
IF ((( NOT(rst)) = '1') AND (RISING_EDGE(clk))) THEN
val <= val_next;
END IF;
instead of :
IF ((rst = '1') AND (RISING_EDGE(clk))) THEN
val <= STD_LOGIC_VECTOR(TO_UNSIGNED(0, val'LENGTH));
ELSE
val <= val_next;
END IF;
The circuit database has to be somehow implemented in every project related to HDL/FPGA etc.
This leads to ridiculous amount of work for developers of such a libraries and also makes this libraries incompatible because their internal representation of circuit is different and exporting/importing of Verilog/VHDL/FIRRTL is not an effective solution.
In fact this implies that very few of just HW optimization libraries exists.
Plan is to search for use cases https://github.com/HardwareIR/hardwareIr/wiki, f4pga/ideas#19 and who would like to use such a library.
Expected library contains:
Similar functionality is implemented in many projects including de facto all HDL/FPGA related project.
I would gladly just extract the implementation from yosys but it is far more complicated than this and there is very strong will of many other projects to use their current solutions and simply do not make the projects compatible because the authors do not see the profit and it is quite lot of work.
For me it is hard to explain them that they should not lose years on developing of own custom half working HDL parser/generator which will die together with their project because 4K men-hours is likely the time required to develop proposed library and even if it may seems as an easy task in the beginning. Also own custom solution means incompatibility.
Also it is extremely important to finis this library in reasonable time, that means in Q2 2019, I mean I need more committers and testers.
ENTITY AxiLiteSlaveContainer IS
GENERIC (
ADDR_WIDTH : INTEGER := <Param, val=8>;
DATA_WIDTH : INTEGER := <Param, val=8>
...
I am getting
No module named 'hdlConvertorAst.translate._verilog_to_basic_hdl_sim_model'
when doing python simple.py
I have installed both hwt
and hwtlib
packages, and I see how all dependances got installed properly. If I do a
pip freeze | grep hdlConvertorAst
, I get hdlConvertorAst==0.8
Any idea on how to debug this further?
Thanks!
Names of signal, interface or component
.name
-> ._name
- logical name, name from user description._name
-> ._hdlName
- physical name, full name with resolved name collisions etc.Backward type reference of signals and constant
._dtype
-> ._ht
def tv(signal):
return signal._dtype.getConstCls()
class RtlSignalOps():
def __invert__(self):
return self.naryOp(AllOps.NOT, tv(self).__invert__)
# currently the const class contains code also for signal/variable operator
class BitsConst:
def __invert__(self):
if isinstance(self, HConst):
return Bits3val.__invert__(self)
else:
...
flatten to parent:
It seems that index on multidimensional arrays is like this:
mem(1)(1)
not like this:
mem(1, 1)
as it should be.
FPGA world suffers a lot from fragmentation - some tools produce Verilog, some VHDL, some - only subsets of them, creating low-level LLVM-like alternative will help everyone, so HDL implementations will opt only for generating this low-level HDL and routing/synthesizers accept it. LLVM or WebAssembly - you can see how many languages and targets are supported now by both. With more open source tools for FPGA this is more feasible now than ever.
See f4pga/ideas#19
Currently all parameter on all sub-interfaces are present in target HDL. Problem is that it is too much lines of text which is usually completely useless.
Proposed solutions:
This library already exists, but it is not public.
This library maybe should be Linux package instead, but installation by setuptools may be an option.
Current implementation is is universal API which can be used with real hardware or on remote hardware or simulator on demand.
Currently it is user space library but currently it is not a problem.
But current connection to simulator is more or less and adhoc.
~ 2018-06-30
XCI contains parameters of ipcore.
component.xml contains definitions of bus interfaces.
Import xci as a Unit instance.
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.