pymtl / pymtl3 Goto Github PK
View Code? Open in Web Editor NEWPymtl 3 (Mamba), an open-source Python-based hardware generation, simulation, and verification framework
License: BSD 3-Clause "New" or "Revised" License
Pymtl 3 (Mamba), an open-source Python-based hardware generation, simulation, and verification framework
License: BSD 3-Clause "New" or "Revised" License
To perform arbitrary Verilog import, the current PyMTL implementation actually assumes the names of ports in the Placeholder
component has to be the same as those in the top level Verilog module. This is obviously not a sound assumption and a better approach (which pymtl v2 does) is to support a port name mapping between the python ports and the Verilog ports.
After #20 is merged, it will be possible to run futurize --stage2
in CI, then run the test suite against Python 3.
(In our quick experiments on Monday, stage 2 changed the behaviour of exec
and broke the tests on Python 2. We'll want to fix that before the tutorial in June, but we can start testing against Python 3 even before we adopt those changes on master.)
Once we're running multiple Python versions in CI, it might also be useful to test against PyPy as well as Python 3 - even without the customized Bits support it should work as that's "just" a performance optimization. Perhaps we should even test on PyPy3!
We should move to Python 3 ASAP
Is there a particular reason why the call method is overwritten for the Bits datatype, as in:
def __call__( self ):
return Bits( self.nbits )
It does not seem intuitive to me that calling an instance of a Bits object should provide another Bits object with the same number of bits, but equal to zero.
I am writing a CL model and have a parameter that is set as an argument to my component. Based on that parameter, I would like to set some helper variables, like so:
def construct( s, x_major = True):
if x_major:
# Rename to make things easier
s.row_len = s.num_y
s.col_len = s.num_x
s.curr_row = s.curr_y
s.curr_col = s.curr_x
else:
s.col_len = s.num_y
s.row_len = s.num_x
s.curr_col = s.curr_y
s.curr_row = s.curr_x
where the items on the RHS are declared as Bits, and in the s.update block are updated using the +=1 increment, so that I can step through a grid. But, doing something like
s.curr_x += 1
actually creates a new Bits object and stores it in curr_x (i.e. it is not updating the value stored in the Bits object, since it is not modeling a register). And thus, something like s.curr_col
would no longer point to the right object like I would like it to.
What is the best way to achieve this desired functionality using PyMTL3? I am currently just setting these helper variables in the s.update block, but I would prefer to have it outside the block in just the construct function.
I would also like to suggest the creation of a forum for PyMTL3, like those used for projects such as TVM. This would help prevent cluttering the github repo issues with questions like these, which are not related to the implementation but rather usage.
Yanghui Ou:
It seems that I cannot connect a bits interface to a bitstruct interface nor does s.bitstruct_wire //= s.bits_wire
seem to work.
s.bitstruct_wire @= s.bits_wire
works. We may want to make it consistent?
To reproduce, use the following code:
from pymtl3 import *
BitStruct = mk_bitstruct( "BitStruct", {
"foo" : Bits32,
} )
class A( Component ):
def construct( s ):
s.in_ = InPort( BitStruct )
s.out = OutPort( 16 )
@update
def upblk():
s.out @= s.in_[0:16]
A().elaborate()
The slicing error on line s.out @= s.in_[0:16]
gives the following error messages which do not refer to the offending signals:
(python3.7.4) [pp@server] $ python3 slice.py
Traceback (most recent call last):
File "slice.py", line 18, in <module>
A().elaborate()
File "/.../pymtl3/dsl/Component.py", line 439, in elaborate
super().elaborate()
File "/.../pymtl3/dsl/ComponentLevel2.py", line 615, in elaborate
c._elaborate_read_write_func()
File "/.../pymtl3/dsl/ComponentLevel2.py", line 301, in _elaborate_read_write_func
s._dsl.upblk_reads [ blk ] = extract_obj_from_names( blk, name_rd[ name ] )
File "/.../pymtl3/dsl/ComponentLevel2.py", line 210, in extract_obj_from_names
lookup_variable( s, 1, 1 )
File "/.../pymtl3/dsl/ComponentLevel2.py", line 191, in lookup_variable
else: expand_array_index( child, name_depth, node_depth+1, 0, idx )
File "/.../pymtl3/dsl/ComponentLevel2.py", line 154, in expand_array_index
child = obj[ current_idx ]
File "/.../pymtl3/dsl/Connectable.py", line 233, in __getitem__
raise InvalidConnectionError( "We don't allow slicing on non-Bits signals." )
pymtl3.dsl.errors.InvalidConnectionError: We don't allow slicing on non-Bits signals.
https://black.readthedocs.io/en/stable/
Black has rapidly become the de-facto standard code formatter for the Python community, and is used by a wide range of projects including both Pytest and Hypothesis.
My own experience with it has been very positive - I no longer think about code formatting at all, which subjectively is a 20-30% boost in available brainpower to solve real problems (or think about more impactful areas of code style, such as interface design).
This will be a substantial change from PyMTL's current code format, and like every change will be a little uncomfortable initially. When Hypothesis adopted Black, this period lasted about two days of working with the code (around a week overall, as we finished rebasing and merging open pull requests).
With regard to timing, I would suggest that we merge @ptpan's work on translation passes (perhaps in several smaller chunks) as soon as practical, get Python 3 running in CI both for tests and because Black can format but not be run on Python 2, and then adopt it as soon as possible.
This will also unlock usage of static analysis using flake8
(and plugins), which are not currently useful due to the nonstandard code format of PyMTL.
I think we will be using slices instead of creating wires for each struct field/array element in the yosys backend. This avoids the incoherent field problem at the cost of not being able to support all pymtl constructs, which is fine because the yosys backend targets the less-expressive Verilog HDL. In this way we still have an option for open-source (using yosys) AET analysis pass.
I'm trying to use the spring20-ece5745
branch to translate pymtl3-proc
. I'm running into an assertion error in DelayPipeCL
which is not triggered if I use the master
branch.
How to reproduce this using spring20-ece5745
branch:
% git clone [email protected]:cornell-brg/pymtl3-proc.git
% cd pymtl3-proc/simple_proc/tests
% pytest ProcRTL_test.py -v -x --tb=long -k test_lw[dest_dep-gen_dest_dep_test]
Error message:
================================================================================================== FAILURES ==================================================================================================
_____________________________________________________________________________ ProcRTL_Tests.test_lw[dest_dep-gen_dest_dep_test] ______________________________________________________________________________
ProcFL_test.py:162: in test_lw
s.run_sim( th, test )
ProcRTL_test.py:55: in run_sim
th.tick()
/home/qtt2/venv/lib/python3.7/site-packages/pymtl3/passes/sim/SimpleTickPass.py:28: in iterative
blk()
/home/qtt2/venv/lib/python3.7/site-packages/pymtl3/stdlib/ifcs/SendRecvIfc.py:223: in up_send_cl
s.send( s.sent_msg.clone() )
/home/qtt2/venv/lib/python3.7/site-packages/pymtl3/dsl/Connectable.py:480: in __call__
return s.method( *args, **kwargs )
/home/qtt2/venv/lib/python3.7/site-packages/pymtl3/dsl/Connectable.py:401: in __call__
return self.method( *args, **kwargs )
/home/qtt2/venv/lib/python3.7/site-packages/pymtl3/passes/tracing/CLLineTracePass.py:52: in <lambda>
mport.method = lambda *args, **kwargs : wrapped_method( mport, *args, **kwargs )
/home/qtt2/venv/lib/python3.7/site-packages/pymtl3/passes/tracing/CLLineTracePass.py:51: in wrapped_method
return driver_method( *args, **kwargs )
/home/qtt2/venv/lib/python3.7/site-packages/pymtl3/dsl/Connectable.py:401: in __call__
return self.method( *args, **kwargs )
/home/qtt2/venv/lib/python3.7/site-packages/pymtl3/passes/tracing/CLLineTracePass.py:43: in <lambda>
mport.method = lambda *args, **kwargs : wrapped_method( mport, *args, **kwargs )
/home/qtt2/venv/lib/python3.7/site-packages/pymtl3/passes/tracing/CLLineTracePass.py:36: in wrapped_method
ret = self.raw_method( *args, **kwargs )
/home/qtt2/venv/lib/python3.7/site-packages/pymtl3/stdlib/cl/StallCL.py:22: in recv
s.send( msg )
/home/qtt2/venv/lib/python3.7/site-packages/pymtl3/dsl/Connectable.py:480: in __call__
return s.method( *args, **kwargs )
/home/qtt2/venv/lib/python3.7/site-packages/pymtl3/dsl/Connectable.py:401: in __call__
return self.method( *args, **kwargs )
/home/qtt2/venv/lib/python3.7/site-packages/pymtl3/passes/tracing/CLLineTracePass.py:52: in <lambda>
mport.method = lambda *args, **kwargs : wrapped_method( mport, *args, **kwargs )
/home/qtt2/venv/lib/python3.7/site-packages/pymtl3/passes/tracing/CLLineTracePass.py:51: in wrapped_method
return driver_method( *args, **kwargs )
/home/qtt2/venv/lib/python3.7/site-packages/pymtl3/dsl/Connectable.py:401: in __call__
return self.method( *args, **kwargs )
/home/qtt2/venv/lib/python3.7/site-packages/pymtl3/passes/tracing/CLLineTracePass.py:43: in <lambda>
mport.method = lambda *args, **kwargs : wrapped_method( mport, *args, **kwargs )
/home/qtt2/venv/lib/python3.7/site-packages/pymtl3/passes/tracing/CLLineTracePass.py:36: in wrapped_method
ret = self.raw_method( *args, **kwargs )
/home/qtt2/venv/lib/python3.7/site-packages/pymtl3/stdlib/cl/DelayPipeCL.py:20: in enq
assert s.pipeline[0] is None
E AssertionError
For example, one way to do In travis we set a backdoor flag in environment, in your pass you check if there is a flag. If so we disable some optimizations to make compilation faster. This can speed up travis runs.
However, if we will run some long simulation in pymtl repo in travis. If so, we might want to spend the compilation overhead to speed up simulation.
In README.md, it writes:
You can install Verilator using the standard package manager but the version available in the package repositories is several years old. This means you will need to build and install Verilator from source
However, the Verilator in APT package repos are very new:
Verilator 4.038 2020-07-11 rev v4.036-114-g0cd4a57ad
Since to use package repos is better than building from source, is it better to instruct users to use package repos?
pymtl3/pymtl3/datatypes/PythonBits.py
Line 218 in a97f2a5
Usually, it would use add on the left operand instead, but not always. For example, if self is actually an instance of a subclass of Bits, but other is an instance of regular old Bits. The subclass might have some extra state to take care of, so its radd is called instead of the parent's add. (Recent optimizations may have changed this for cases when the subclass does not actually redefine radd.)
This issue is Zac's notes-to-self, but feedback is welcome!
&
and |
masks)I don't think upstream support for this strategy is useful in this case, as we can draw raw bytes from the st.binary()
strategy and do bit-twiddling on top of the Hypothesis API but within the PyMTL API - the best of both worlds.
I'm inclined to put this in a new pymtl.hypothesis.*
namespace, for all strategies and Hypothesis testing helpers. Thoughts?
Hello.
I'm now trying to use pymtl3, but the script incurs ".tf file except error."
I think the source code does not have .tf file. (even though other FreePDK files exist )
How can I circumvent this issue?
Thanks.
We currently use $
as a separator in the translation passes. Despite the fact that DC can handle signal names with $
s pretty well, some ASIC tools fail subtly if they see signal names with $
. For example, Synopsys vcat utility rejects a configuration file that mentions dollar-sign signals in the VCD file, without mentioning the use of $
.
If $
are generally not used in common Verilog source code, then we probably should consider switch to other characters (maybe _
?) for the sake of better integration with other tools... Thoughts? @jsn1993
In the past semester, we have been gaining deeper understanding and more neat ideas. The team has been trying hard to address showstoppers. Right now, we have 7 weeks before we release pymtl3 for FCRC 2019 tutorial. I think there are three categories of features we want to work on. Here is a tentative list of all the action items I can think of at this moment.
Category 1: Mamba - PyMTL 3 as a Python project
Category 2: Matching the PyMTL 2 features
Category 3: Mamba-exclusive
Category 4: Tutorial-specific
qflow
translation/import backend since we are targeting the open source ASIC flow in the tutorial.in tutorial slides (https://www.csl.cornell.edu/pymtl2019/pymtl-tutorial-ex01-isca2019.pdf) on pages like 25 and 29 you use s.connect() to connect two wires but it should be connect().
TBD
PyMTL 3 implicitly adds clk
and reset
ports to every component to ensure the framework has a reliable way to reset and tick components during simulation. Both clk
and reset
will be collected and translated as if they are ports added by users. However it's not safe to assume the desired clock and reset signal name are always clk
and reset
, especially when trying to integrate PyMTL-generated code with other RTL designs.
One possible solution is to add flags to components indicating the exclusion of clk
and/or reset
signals. Under these flags, it becomes the user's responsibility to create and connect clock and reset signals correctly. Note that component simulation will still use the implicit clk
and reset
.
The current PyMTL 3 behavioral modeling does not support MsgType.MEM_AMO
syntax if MsgType
is a Python class or an instance of a Python class. The translation pass does not know the hardware correspondent of MsgType
and chooses to abort the translation.
It would be nice to support the above syntax and translate it to SystemVerilog enum
data type.
The current translation tests are in sverilog/ and it's set up such that you have to provide a._ref_src_yosys or even a._ref_src_other_backend in sverilog/ which is not clean enough. We don't want to have stuff related to other backends inside the sverilog/.
The current yosys backend supports indexing into an array with signals or loop variables (i.e. the "dynamic" values). This feature is orthogonal to the choice of backend and should be back-ported to SystemVerilog backend, which will be our most-used backend that drives ASIC/FPGA flows.
I ran into some unexpected behavior as a result of the determination of the size the result of operations as specified here. For example, the behavior of add is defined as:
def __add__( self, other ):
try: return Bits( max(self.nbits, other.nbits), int(self.value) + int(other) )
except: return Bits( self.nbits, int(self.value) + int(other) )
However, I believe the correct behavior should be
def __add__( self, other ):
try: return Bits( max(self.nbits, other.nbits)+1, int(self.value) + int(other) )
except: return Bits( self.nbits+1, int(self.value) + int(other) )
I believe that this definition matches the behavior of HDLs such as Verilog. For example,
module add(i_clk, a, b, out);
input wire [1:0] a;
input wire [1:0] b;
output reg [2:0] out;
always @(posedge i_clk)
out <= a + b;
would work as expected when a = 2 and b = 2.
However,
from pymtl3 import *
a = Bits2(2)
b = Bits2(2)
c = a + b
does not work as expected, as c results in Bits2(2), not Bits3(4).
Similarly, the bit width definition for multiply is incorrect, and should be the addition of the two bit widths (since unsigned multiplication is being defined as the default).
Finally, I believe that it would be beneficial to add in some sort of casting of constants to Bits, also to avoid unexpected results.
For example,
def __add__( self, other ):
try: return Bits( max(self.nbits, other.nbits)+1, int(self.value) + int(other) )
except:
other = Bits32(other)
return Bits( max(self.nbits, other.nbits)+1, int(self.value) + int(other) )
Again, I believe that this matches the behavior of Verilog, where a constant without a defined bit_width is assumed to be 32 bits. Otherwise, you run into unexpected bugs, such as
from pymtl3 import *
a = Bits2(3)
c = a + 3 # c now holds 2, instead of 4
from pymtl3 import *
from pymtl3.passes.GenDAGPass import GenDAGPass
from pymtl3.passes.OpenLoopCLPass import OpenLoopCLPass
class QueueCL( Component ):
def construct( s, maxsize ):
s.q = deque( maxlen=maxsize )
s.add_constraints( M(s.deq) < M(s.enq) )
@non_blocking( lambda s: len(s.q) < s.q.maxlen )
def enq( s, value ):
s.q.appendleft( value )
@non_blocking( lambda s: len(s.q) > 0 )
def deq( s ):
return s.q.pop()
def line_trace( s ):
return str(s.enq) + "()" + str(s.deq)
class TwoQueueCL( Component ):
def construct( s ):
s.enq = NonBlockingCalleeIfc()
s.deq = NonBlockingCalleeIfc()
s.q1 = QueueCL(2)
s.q2 = QueueCL(2)
s.connect( s.enq, s.q1.enq )
s.connect( s.q2.deq, s.deq )
@s.update
def upA():
if s.q1.deq.rdy() and s.q2.enq.rdy():
s.q2.enq( s.q1.deq() )
def line_trace( s ):
return str(s.enq) + "()" + str(s.deq)
A = TwoQueueCL()
A.elaborate()
A.apply( GenDAGPass() )
A.apply( OpenLoopCLPass() )
A.lock_in_simulation()
if A.enq.rdy():
A.enq(3)
if A.enq.rdy():
A.enq(4)
if A.enq.rdy():
A.enq(5)
if A.deq.rdy():
print A.deq()
if A.deq.rdy():
print A.deq()
if A.deq.rdy():
print A.deq()
In this example, upA calls s.q1.deq and I currently fail to handle this dependency of top level s.enq < s.q1.deq = upA.
s.connect( s.x, req_type(0x100, 100))
Is it necessary to add some memory simulation models such as DRAMSim2 if I want to do some simulation with memory access ?
The current PyMTL translation pass generates a pretty long name that includes the names and values of parameters. This naming scheme becomes awkward when a component has several parameters and when these parameters have long names. We even experienced verilator compilation error when the translated name of some component grows too long (> 100 characters?). Also there are situations where customized component names are useful (e.g. integrating PyMTL generated designs with larger projects where we want to swap in PyMTL generated components without changing the external design code; also in our ASIC flow scripts it would be nice to use the same name for the top component).
We need (1) a way to make component names shorter (hashing?) and (2) to provide support for customized component names (a mapping between parameters and name?).
The GenDAGPass is not throwing very useful error message for CL modeling. Often I just get an E AttributeError: 'CallerPort' object has no attribute 'get_sibling_slices'
, which is kind of confusing.
Such API can remove some parameters for construction
def construct( s, DecoderType ):
s.decoder = DecoderType()
s.branch_type = Wire( s.decoder.branch_type.get_datatype() )
Since we already have a standardized bitstruct, it's time to add the hypothesis strategy for bitstruct to datatypes/?
Hello,
I was wondering if there is any module in the stdlib for a memory master that is aware of what type of queue is connected to the response port. Essentially, say I have:
s.sdram = MemMasterIfcCL( memreq_cls, memresp_cls )
s.sdramresp_q = NormalQueueCL(num_entries=3)( enq=s.sdram.resp )
I would like to have s.sdram.req.rdy() evaluate to true iff there will be room in s.sdramresp_q
This logic is relatively straightforward to do in my module, but I need to do this multiple times for different modules so I was wondering if there is any stdlib support for this. If not, and you think this could be broadly useful, I may be able to try to come up with a solution and push that out
To better support other Verilog/SystemVerilog-based projects that use Verilator for simulation, it would be nice to have the following features:
-f
option)rpath
during the actual C++ test bench compilationI'm trying the example from this lecture.
Code from Figure 8 and Figure 9 there.
The code fails:
$ ./sim.py
Traceback (most recent call last):
File "./sim.py", line 8, in <module>
from RegIncr import RegIncr
File "/disk-samsung/freebsd-ports/cad/py-pymtl/RegIncr.py", line 35, in <module>
def block2():
File "/usr/local/lib/python3.8/site-packages/pymtl3/dsl/ComponentLevel1.py", line 28, in update
NamedObject._elaborate_stack[-1]._update( blk )
AttributeError: type object 'NamedObject' has no attribute '_elaborate_stack'
I think there are three distinct stages of gradual typing for PyMTL:
For example, running mypy --py2 --ignore-missing-imports pymtl
emits the following messages:
pymtl\dsl\Connectable.py:10: error: Module 'pymtl.datatypes' has no attribute 'mk_bits'
pymtl\dsl\Component.py:9: error: Module 'pymtl.datatypes' has no attribute 'Bits1'
pymtl\dsl\test\Interface_test.py:40: error: Name 'Interface' is not defined
pymtl\dsl\test\Interface_test.py:51: error: Name 'Interface' is not defined
pymtl\dsl\test\ComponentLevel3_test.py:454: error: Name 'test_connect_list_idx_call' already defined on line 113
pymtl\datatypes\bits_import.py:36: error: Need type annotation for '_bits_types'
So it's already uncovered a bug in the tests, and potential AttributeErrors to investigate.
Adding type annotations, initially using the comment-based syntax for Python 2 support, will only make this more powerful. The official quickstart guide and this report from Zulip give a good sense of how to incrementally adopt static types. Instagram's MonkeyType library might also help - it observes the argument types at runtime (e.g. in tests) and adds annotations for you - but I don't have any direct experience with that.
Similarly to any coverage metric - define the areas that need to be covered, and fail the build in CI if they are not fully covered. Mypy supports a wide range of criteria for this, including for example "no calls from typed to untyped functions", which can be toggled on a per-file, per-directory, or per-project basis.
At this stage it may be worth investigating e.g. how to express size constraints on Bits arguments through the type system - I'm confident that it's possible to express, but might be overly verbose or not yet handled by Mypy.
Up the research end, gradual typing could have some place in translation or validation passes; or perhaps PyMTL could ship a mypy plugin for PyMTL users to check their code. This stage is fairly blue-sky!
I'd aim to get some hands-on experience with the basics in stage one, then work out what of stage two will be useful and what you might want to try in stage three.
Hi, and I'm using PyMTL to design hardware where we need to generate different case statements according to the given arguments. I have searched for anything about "case" in the source code but I don't think the case statement is supported at present? Do you have plan for it? Thanks!
Is it possible to enforce constraints imposed on blocks across components? I am not quite sure how I would access such a block, since they are functions declared within the construct function. What I would like to be able to do is something like:
s.add_constraints(
U(s.reader.AddrGen) < U(s.CheckConsistency),
U(s.writer.Write) < U(s.CheckConsistency),
U(s.CheckConsistency) < U(s.reader.Read)
)
where 'reader' and 'writer' are separate Components, which are instantiated inside of a MemoryController where I am trying to impose these constraints, and 'AddrGen', 'Write', and 'Read' are @s.update blocks inside the Reader and Writer compoents. CheckConsistency is a block inside the MemoryController.
Thanks!
Jake
We want to introduce the Verilog-style assign statements into the dsl.
s.connect( s.x, lambda: s.y + 1 ) # assign s.x = s.y + 1
Apparently PyMTL doesn't support multiple clock domains? Supporting multiple clock domains is really essential. It is the only way to get high speed designs into FPGA devices.
I am on a MacBook Pro (High Sierra 10.13.6) and have downloaded Verilator 4.224 source code.
However, upon issuing "make" command, I do get the following error message:
Undefined symbols for architecture x86_64:
"sc_time_stamp()", referenced from:
vl_time_stamp64() in Vt_a1_first_cc__main.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[1]: *** [Vt_a1_first_cc] Error 1
I am not a software engineer, so I do appreciate if someone could clearly provide a detailed step by step resolution (if any) to me to remove the above error message.
Having a gigantic block of
s.connect( s.x1, s.y1 )
s.connect( s.x2, s.y2 )
...
seems annoying.
We are considering adding some syntactic sugar
s.x1 //= s.y1
s.x2 //= s.y2
...
to wrap around s.connect.
There are a few selections:
|=, <<=, /=
. The good thing about assign-based is the implied directionality, but WHENEVER WE INTRODUCE A CONSTANT, it becomes really ambiguous and confusing:s.x |= 1
s.y <<= 2
s.z /= 2
//
. This operator is perfect except that when we implement both floordiv and rfloordiv,123 // s.out
looks seriously like a C/verilog style comment ...
I just used @s.update
instead of @s.update_ff
for a sequential block and pymtl3 didn't complain. When trying to translate it Verilator gives me this error:
E Verilator output:
E %Warning-COMBDLY: SwitchUnitMFlitRTL__a78c05a9be637c7c.sv:558: Delayed assignments (<=) in non-clocked (non flop or latch) block
E : ... Suggest blocking assignments (=)
We should probably check this during elaboration? I think we check @s.update_ff
but seems not @s.update
I found that in 32-bit system we might not be able to use "long" when we generate the cpp wrapper for verilator.
Is it possible in a CL model to have conditional elaboration? What I mean is the following:
I have a parametrized model with two modes-- for example, a CRC that operates either on one piece of data or an array. I'd like to have just one PyMTL CL model as follow:
class CRC( Component ):
def construct(s, arr=True):
< common defs>
if arr:
s.done = Bits1(0)
s.length = InPort( Bits1 )
<more stuff>
@s.update
def crc(s):
<common stuff>
if arr:
if count == s.length:
s.done = Bits1(1)
<more stuff>
But when I attempt something like that, I receive an undefined error if arr is False, even though the undefined variables will never be reached.
Is there an accepted PyMTL practice for this kind of setup?
Thanks!
To reproduce
from pymtl3 import *
class Comp( Component ):
def construct( s ):
s.y = OutPort( Bits1 )
s.z = OutPort( Bits1 )
s.x = InPort( Bits1 )
s.y //= b1(1)
s.z //= s.x
class Top( Component ):
def construct( s ):
s.comp = Comp()
s.comp.x //= s.comp.y # elaboration time error
if __name__ == "__main__":
a = Top()
a.elaborate()
generates the following exception. This is not an expected behavior because the connection happens at the parent module Top
pymtl3.dsl.errors.SignalTypeError: [Type 5] Invalid port type detected at the same host component "s.comp" (class Comp)
- InPort "s.comp.x" cannot be driven by OutPort "s.comp.y".
Note: InPort x.y cannot be driven by x.z
I always use pkg-config to get verilator include path. However, after we move to Python 3, I got the following error when I try to run the import tests.
$ pytest ../pymtl3/passes/sverilog/test/TranslationImport_closed_loop_directed_test.py
...
_________________________________________________________ test_bypass_queue_stall __________________________________________________________
../pymtl3/passes/sverilog/test/TranslationImport_closed_loop_directed_test.py:106: in test_bypass_queue_stall
test_func()
../pymtl3/stdlib/rtl/enrdy_queues_test.py:79: in test_bypass_queue_stall
run_sim( TestHarness( Bits32, BypassQueue1RTL(Bits32), req, resp, 3, 4 ) )
../pymtl3/passes/sverilog/test/TranslationImport_closed_loop_directed_test.py:34: in run_sim
th = TranslationImportPass()( _th )
../pymtl3/passes/sverilog/TranslationImportPass.py:22: in __call__
return s.get_import_pass()( top )
../pymtl3/passes/sverilog/import_/ImportPass.py:61: in __call__
ret = s.traverse_hierarchy( top )
../pymtl3/passes/sverilog/import_/ImportPass.py:74: in traverse_hierarchy
s.traverse_hierarchy( child )
../pymtl3/passes/sverilog/import_/ImportPass.py:71: in traverse_hierarchy
return s.do_import( m )
../pymtl3/passes/sverilog/import_/ImportPass.py:78: in do_import
imp = s.get_imported_object( m )
../pymtl3/passes/sverilog/import_/ImportPass.py:155: in get_imported_object
s.create_shared_lib( m, config, cached )
../pymtl3/passes/sverilog/import_/ImportPass.py:272: in create_shared_lib
cmd = config.create_cc_cmd()
../pymtl3/passes/sverilog/import_/ImportConfigs.py:253: in create_cc_cmd
c_include_path = " ".join("-I"+p for p in s.get_all_includes() if p)
../pymtl3/passes/sverilog/import_/ImportConfigs.py:419: in get_all_includes
includes += [vl_include_dir, vl_include_dir + "/vltstd"]
E TypeError: can't concat str to bytes
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.