Code Monkey home page Code Monkey logo

pymtl3's People

Contributors

cbatten avatar dependabot[bot] avatar jbrzozo24 avatar jsn1993 avatar kaishuocheng avatar mondo avatar nfc35 avatar ptpan avatar qtt2 avatar tancheng avatar yo96 avatar yodada avatar zac-hd avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pymtl3's Issues

Customized port name mapping during import

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.

Run tests against PyPy and Python 3 on Travis

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!

Bits call method

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.

Setting up renamed signals

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.

Support s.bitstruct_wire //= s.bits_wire

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?

Slicing non-Bits signals inside update blocks does not generate very helpful error messages

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.

Adopt the Black code style

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.

Plan for yosys translation backend

A note about the future of yosys backend

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.

Assertion error in DelayPipeCL

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

Add a backdoor flag to disable verilator/c++ optimizations flags to make travis run faster

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.

README Verilator sentences

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?

Assuming other is not Bits?

# TODO can we assume other is not Bits?

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.)

Design / review a custom Hypothesis strategy for Bits

This issue is Zac's notes-to-self, but feedback is welcome!

  • How do people use bits in tests?
  • What arguments should be required or optional?
  • Are masks a useful feature? (both & 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?

Things to fix

  • Add special error message for declaring ports using InVPort( 1 ) which should be InVPort(mk_bits(1))
  • Change the way to handle data structs by instantiating an instance and then getitem
  • Don't check if two interfaces have the same type if they don't have any Type field (assert o1.Type == o2.Type)

How can it get .tf file?

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.

The use of `$` as separators during translation upsets some ASIC tools

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

Action items for the next 7 weeks before June 22 ISCA tutorial

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.

Please do propose additional action items if I miss any, or you think is important

Category 1: Mamba - PyMTL 3 as a Python project

  • Make PyMTL installable on PyPI via pip. Need to add setup.py at top level just like the pymtl repo.
  • Move the whole project to Python 3.
  • Come up with a a better top level README with TravisCI/Coverage status indicators, installation instructions, and dependencies.
  • removed.. Reorganize pymtl-v3-design in a better way.
  • removed.. Potentially adopt a better code style such as black's style.
  • more ...

Category 2: Matching the PyMTL 2 features

  • Merge in the translation branch and get the whole team to be familiar with the software architecture. Peitian has been individually working on this branch for a really long while and it's important for the whole team to keep in sync.
  • Add manual connect support for Send/Recv CL/RTL interfaces in pclib so that CL/RTL components are actually composed by methods.
  • VCD dumping pass
  • A better Bits struct implementation.
  • Figure out useful FL interfaces.
  • Figure out a way to tell the user not to instantiate any component/port/interface in init
  • More robust testing of the dynamic scheduling pass.
  • Drastically improving the update block error message to add detailed line numbers of file.
  • more ...

Category 3: Mamba-exclusive

  • Connecting a constant struct to a port with struct type to avoid net-no-writer.
  • Come up with a better folder structure in pymtl/passes. Organize the passes as top-level and leaf-level passes.
  • Implement M(x)==M(y) constraints
  • Implement hypothesis strategy for Bits.
  • Slightly tune the simulation performance of the dynamic scheduling pass (maybe do this before DAC deadline instead).
  • A more complete implementation of RPython Bits.
  • Add example analysis passes. Fix transform passes and APIs.
  • more ...

Category 4: Tutorial-specific

  • Making a TinyRV1 CL processor using method-based interfaces.
  • Add a qflow translation/import backend since we are targeting the open source ASIC flow in the tutorial.
  • more ...

Better handling of implicit `clk` and `reset` during translation

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.

Add translation support for SystemVerilog `enum` data type

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.

Reuse the translation tests in a better way across backends

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/.

Back-port dynamic index feature to SystemVerilog backend

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.

Bit sizing in ops

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

Handle U-M1-M2 constraint chain when M is a top level method

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.

Better names for translated components with parameters

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?).

Error message in GenDAGPass

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.

Response-Aware Memory Master

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

Integration with other Verilog-based projects

To better support other Verilog/SystemVerilog-based projects that use Verilator for simulation, it would be nice to have the following features:

  1. Passing customized file list to Verilator (-f option)
  2. Support for more Verilator options, especially those used to suppress warnings
  3. Linking the shared library against other libraries
  4. #73
  5. Instantiating a Verilog module with parameters
  6. More advanced flags such as setting rpath during the actual C++ test bench compilation

Example fails: type object 'NamedObject' has no attribute '_elaborate_stack'

I'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'

example.zip

Experiment with gradual typing, checked using mypy

I think there are three distinct stages of gradual typing for PyMTL:

Static typing as a useful linter

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.

Minimize un-annotated code

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.

Gradual typing in PyMTL

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.

Add translation support for case.

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!

Enforcing constraints across components

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

Support multiple clock domains

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.

Failed to compile Verilator 4.224

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.

Syntactic sugar for s.connect

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:

  1. Assign-based |=, <<=, /=. 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
  1. //. This operator is perfect except that when we implement both floordiv and rfloordiv,
123 // s.out

looks seriously like a C/verilog style comment ...

No error or warning thrown when using `<<=` in a update block

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

Conditional Elaboration

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!

TODO list

  • Implement model.apply( Pass() ) and model.apply( [ Pass1(), Pass2() ] )
  • Implement def construct_ifc() in addition to construct_impl

Connecting output port of component A to its own input port

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

Fixing byte/str concatenation when using pkg-config during import

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

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.