GithubHelp home page GithubHelp logo

phanrahan / magma Goto Github PK

View Code? Open in Web Editor NEW
239.0 239.0 22.0 21.52 MB

magma circuits

License: Other

Python 50.69% Verilog 22.48% Shell 0.08% SystemVerilog 0.92% C++ 0.16% MLIR 24.52% V 0.71% Smarty 0.44%

magma's People

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

magma's Issues

Change Register(ce=False) to Register(has_ce=False)

Make it obvious that this is generating a register with a clock enable, not that we are wiring up a clock enable.

This should be done to all primitives with clock signals (including counters, shift registers, etc.)

Document magma higher order functions

These features are very powerful but a bit hard to understand, would be great to have:

  • Documentation on each supported function
    • braid
    • row
    • col
    • join
    • fork
    • flat
    • compose
    • curry
    • uncurry
    • map
  • Tutorials/Examples with demonstrative use cases composing these functions

The magma programming model has an existing section discussing this, but I think it needs to be expanded. There may also be some useful examples in the 488H lecture slides.

Define `__format__` specification for printing circuit components with qualified names

From Python docs:

object.format(self, format_spec)
Called by the format() built-in function (and by extension, the format() method of class str) to produce a “formatted” string representation of an object. The format_spec argument is a string that contains a description of the formatting options desired. The interpretation of the format_spec argument is up to the type implementing format(), however most classes will either delegate formatting to one of the built-in types, or use a similar formatting option syntax.

See Format Specification Mini-Language for a description of the standard formatting syntax.

This should be useful for simulation, but the specification might need to be blocked until we begin integrating the magma simulation code and have a better understanding of how we might use this.

Type conversions

I suggest all type conversions be done in a way similar to standard python type conversions. For example int(x) converts the string s to an int. There are other options like int(s, base).

In particular, we would implement bits(), uint(), and sint().

Here are some variants for bits. Similar versions would exist for uint and sint.

bits(i,n) - convert the python integer i to a magma Bits(n)
bits(b0, b1, ..., bn) - convert n Bit values to a Bits(n) value
bits(uint) - converts a UInt(n) to a Bits(n)
bits(sint) - converts a Sint(n) to Bits(n)

This issue is related to #37

Add a cast operator

  • array(val) and type.as_array()
  • bits(val) and type.as_bits()
  • uint(val) and type.as_uint()
  • sint(val) and type.as_sint()

Bit vs Bool

We should have two Bit types.

One type, say Bit, should only be wireable.

The other type, say Bool, should implement logical operations such as And, Or, Xor, Not.

We should be able to convert between the two.

Clock would be a subtype of Bit. You can only wire clock signals. To perform logical operations on Clock would require it to be converted to a Bool.

In terms of naming, the above suggestions is not ideal. We currently allow logical operations on Bits(n), which by analogy means we should allow logical operations on Bit. Not sure what to name the type which is just wireable.

complete coreir primitives

These primitives need DefineOp, Op and op versions

  • mux
  • negate
  • min, max
  • abs
  • memory

Pseudoprimitives (meta-programmed in python)

  • concat
  • repeat
  • rol, ror

Improve test coverage

Past projects I've worked on have used 90% coverage as a target which seems pretty reasonable.

Report from today (5/24/17) obtained via pytest --cov=magma

Name                                      Stmts   Miss  Cover
-------------------------------------------------------------
magma/__init__.py                            22      1    95%
magma/array.py                              193     48    75%
magma/backend/__init__.py                     0      0   100%
magma/backend/blif.py                       104     86    17%
magma/backend/verilog.py                    134     38    72%
magma/bit.py                                101     20    80%
magma/bits.py                                49     37    24%
magma/bitwise.py                             37     30    19%
magma/board.py                                8      4    50%
magma/circuit.py                            285     81    72%
magma/compatibility.py                        7      2    71%
magma/compile.py                             54     29    46%
magma/compile_abstract.py                    78     78     0%
magma/config.py                               6      0   100%
magma/debug.py                               14      1    93%
magma/error.py                               23      4    83%
magma/fpga.py                                43     34    21%
magma/higher.py                             216     50    77%
magma/interface.py                          206     43    79%
magma/ir.py                                  13      0   100%
magma/part.py                                10      6    40%
magma/peripheral.py                           9      5    44%
magma/port.py                               105     25    76%
magma/python_simulator.py                   160    127    21%
magma/ref.py                                 60      8    87%
magma/scope.py                               26     17    35%
magma/simulator.py                           19      8    58%
magma/simulator_interactive_frontend.py     252    222    12%
magma/t.py                                   58      6    90%
magma/tests.py                               11      0   100%
magma/transforms.py                         147    128    13%
magma/tuple.py                              174     42    76%
magma/wire.py                                96     49    49%
-------------------------------------------------------------
TOTAL                                      2720   1229    55%

Testing interface for primitives

Proposal: test(magma.operator.and_, operator.and_, [Bit, Bits, UInt, SInt])

Where test(magma_primitive_op, python_op, types) will test magma_primitive_op in the Python simulator and Verilator using python_op as a gold function. type is a list of magma types to test the operations on.

Move ice40 simulator to mantle/lattice/ice40

I think it would make more sense to have the ice40 simulator primitives be part of mantle/lattice/ice40.

We can also test the mantle40 code using the yosys implementations of the ice40 primitives. This would allow is to test the mantle40 implementations using verilator.

Explore better syntax for subclassing Circuit

Can we remove the classmethod definition requirement?

In chisel you can write:

class Mux2 extends Module {
  val io = IO(new Bundle{
    val sel = Input(UInt(1.W))
    val in0 = Input(UInt(1.W))
    val in1 = Input(UInt(1.W))
    val out = Output(UInt(1.W))
  })
  io.out := (io.sel & io.in1) | (~io.sel & io.in0)
}

hypothetical python version

class Mux2(Circuit):
  io = IO({
    "sel" : In(Bit),
    "in0" : In(Bit),
    "in1" : In(Bit),
    "out" : Out(Bit)
  })
  io.out = (io.sel & io.in1) | (~io.sel & io.in0)

Clock, Enable, Reset

We should define single Bit types for FFs and change the wireclock logic in compile to test for the type rather than use string names (which is fragile since different vendors use different names for these signals).

  • Clock
  • Enable
  • Reset

Make naming circuits more convenient

Unique names for circuit definitions are needed for implementing caching.

Two possibilites:

  • Provide convenience function for generating the name based on parameters
  • Cache circuits based on something other than names

Clean up naming conventions and interfaces for defining, instancing, and wiring up circuits

Begin with two abstract inputs:

I0 = In(Array(2, Bit))
I1 = In(Array(2, Bit))

Pattern 1: DefineName(args) defines a circuit, which can be instanced and wired up normally

Add2 = DefineAdd(width=2)
add2 = Add2(**instance_args)
add2_O = add2(I0, I1)

Pattern 2: Name(args) defines or retrieves a cached definition of the circuit and instances it

add2 = Add(2, **instance_args) 
add2_O = add2(I0, I1)

Pattern 3: name(args) infers the widths of the inputs, defines or retrieves a cached definition of the circuit, instances it, wires up inputs, and returns output

add2_O = add(I0, I1, **instance_args)

Can't set simulator inputs which aren't wired up

from magma import *
from loam.boards.icestick import IceStick

from magma.python_simulator import PythonSimulator
from magma.scope import *

icestick = IceStick()
icestick.Clock.on()
for i in range(4): icestick.PMOD0[i].input().on()

main = icestick.main()
EndCircuit()

sim = PythonSimulator(main)

scope = Scope()

sim.set_value(main.PMOD0[0], scope, True)

error on last line:

import lattice ice40
import lattice mantle40
Traceback (most recent call last):
  File "/Users/osnr/dev/magmacore/magma/transforms.py", line 35, in get_new_bit
    return self.orig_to_new[QualifiedBit(bit=orig_bit, scope=scope)]
KeyError: QualifiedBit(bit=main.PMOD0[0], scope=<magma.scope.Scope object at 0x102b44d68>)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "tests/test_simulator.py", line 18, in <module>
    sim.set_value(main.PMOD0[0], scope, True)
  File "/Users/osnr/dev/magmacore/magma/python_simulator.py", line 223, in set_value
    newbit = self.txfm.get_new_bit(bit, scope)
  File "/Users/osnr/dev/magmacore/magma/transforms.py", line 37, in get_new_bit
    raise MagmaTransformException("Could not find bit in transform mapping. bit={}, scope={}".format(orig_bit, scope))
magma.transforms.MagmaTransformException: Could not find bit in transform mapping. bit=main.PMOD0[0], scope=<magma.scope.Scope object at 0x102b44d68>

but works if you icestick.D1.on() and wire(main.D1, main.PMOD0[0]), so I guess it's the fact that PMOD0[0] wasn't wired in the example?

I'd find setting unwired inputs useful if I'm commenting out parts of the circuit or doing automatic circuit generation. I guess I could just ignore that exception, since the input doesn't matter anyway.

In(Bits(n))

Print out In(Bits(n)) yields "Bits(n)". Should probably be "In(Bits(n))". Same for Out(Bits(n)).

Similarly, In(UInt(n)) and In(SInt(n)) should print the direction.

Create Bool, SInt, and UInt types that support operator overloading

See Chisel types

Proposed type hierarchy

Bit (Bool = Bit)

  • logical operations &, |, ^, !

Bits(n) = Array(n,Bit)

  • logical operations &, |, ^, ~, >>, <<, ...

UInt(n) \subclass Bits(n)

  • unsigned arithmetic operators +, -, *, /
  • unsigned relational operarors <, <=, >, >=

SInt(n) \subclass Bits(n)

  • signed arithmetic operators +, -, *, /
  • signed relational operarors <, <=, >, >=

Int binop simulation doesn't work for 1-bit output

Example:

from magma import *
from mantle.lattice.mantle40 import Counter

hello = DefineCircuit('hello', 'O', Out(Bit), 'CLK', In(Bit))

counter = Counter(8)
wire(hello.O, counter.O < constarray(3, 8)) # binop with 1-bit output

from magma.python_simulator import PythonSimulator
from magma.scope import Scope

sim = PythonSimulator(hello)
scope = Scope()
sim.evaluate()
print(sim.get_value(hello.O, scope))

yields AssertionError in ValueStore.set_value because "Can only set boolean values".

I think the problem is that the binop simulate implementation in primitives.py always calls as_bool_list() to generate newval, even if newval needs to be just one bool instead of a list of bools.

Would it be better to do this in set_value:

        elif isinstance(newval, list) and len(newval) == 1:
            newval = newval[0]

or to dispatch on the out_type in simulate?

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.