Skip to main content

Kratos is a fast hardware design language embedded in Python

Project description

Build Status PyPI - Format PyPI - Version Documentation Status

Kratos is a hardware design language written in C++/Python. It differentiates itself from other DSL with the following design philosophy:

  • Fully debuggable: users can see a trace of every passes on every verilog statement.

  • Highly efficient: Python frontend powered by Modern C++ binding. Designed with multi-processing in mind.

  • Human-readable verilog: we know how difficult it is to read machine generated verilog. kratos has multiple passes to produce nice-looking verilog.

  • Generator of generators: every python object is a generator that can be modified at any time, even after instantiation. This allows complex passes on the generators without ripping old structure apart.

  • Keep the good parts of verilog: The always block in behavioral verilog is close to other programming languages. Kratos allows you to write python code similar to behavioral verilog

  • Single source of truth: kratos encourages users to infuse generator information inside generator itself. This makes debugging and verification much easier.

  • Static elaboration: kratos allows user to write parametrized code, even in the always block, all in Python.

  • Type checking: kratos check the variable types for each assignment to make sure there is no implicit conversion.

Install

pip install kratos

Pre-built wheels supports all Python 3.5+ on Linux and Python 3.7 on OSX. To build it from scratch, you need a C++17 compatible compiler, such as g++-8.

Documentation and Examples

You can check the documentation at Read the Docs

Here are some examples to showcase the ability of kratos.

Asnyc Reset Register

Python code that parametrizes based on the width. Notice that we specify the sensitivity of the always block when defining seq_code_block.

class AsyncReg(Generator):
    def __init__(self, width):
        super().__init__("register")

        # define inputs and outputs
        self._in = self.input("in", width)
        self._out = self.output("out", width)
        self._clk = self.clock("clk")
        self._rst = self.reset("rst")
        self._val = self.var("val", width)

        # add combination and sequential blocks
        self.add_code(self.seq_code_block)

        self.add_code(self.comb_code_block)

    @always((Posedge, "clk"), (Posedge, "rst"))
    def seq_code_block(self):
        if self._rst:
            self._val = 0
        else:
            self._val = self._in

    def comb_code_block(self):
        self._out = self._val

Here is the generated verilog

module register (
  input  clk,
  input [15:0] in,
  output reg [15:0] out,
  input  rst
);

logic  [15:0] val;

always @(posedge clk, posedge rst) begin
  if rst begin
    val <= 16'h0;
  end
  else begin
    val <= in;
  end
end
always_comb begin
  out = val;
end
endmodule   // register

Fanout module

This is an example to showcase the kratos’ static elaboration ability in always block. In practice we would not write it this way.

class PassThrough(Generator):
    def __init__(self, num_loop):
        super().__init__("PassThrough", True)
        self.in_ = self.input("in", 1)
        self.out_ = self.output("out", num_loop)
        self.num_loop = num_loop

        self.add_code(self.code)

    def code(self):
        if self.in_ == self.const(1, 1):
            for i in range(self.num_loop):
                self.out_[i] = 1
        else:
            for i in range(self.num_loop):
                self.out_[i] = 0

Here is generated verilog

module PassThrough (
  input  in,
  output reg [3:0] out
);

always_comb begin
  if (in == 1'h1) begin
    out[0:0] = 1'h1;
    out[1:1] = 1'h1;
    out[2:2] = 1'h1;
    out[3:3] = 1'h1;
  end
  else begin
    out[0:0] = 1'h0;
    out[1:1] = 1'h0;
    out[2:2] = 1'h0;
    out[3:3] = 1'h0;
  end
end
endmodule   // PassThrough

How to debug

Because Python is quite slow, By default the debug option is off. You can turn on debugging for individual modules. Here is an example on how to turn on debug (see tests/test_generator.py for more details).

class PassThroughMod(Generator):
    def __init__(self):
        super().__init__("mod1", True)
        self.in_ = self.input("in", 1)
        self.out_ = self.output("out", 1)
        self.wire(self.out_, self.in_)

# ... some other code
class Top(Generator):
    def __init__(self):
        super().__init__("top", True)

        self.input("in", 1)
        self.output("out", 1)

        pass_through = PassThroughMod()
        self.add_child_generator("pass", pass_through)
        self.wire(self["pass"].ports["in"], self.ports["in"])

        self.wire(self.ports.out, self["pass"].ports.out)

mod = Top()
mod_src, debug_info = verilog(mod, debug=True)

You can see the generated verilog:

module top (
  input logic  in,
  output logic  out
);

assign out = in;
endmodule   // top

The pass sub-module disappeared due to the compiler optimization. However, if we print out the debug information, we can see the full trace of debug info on assign out = in;

{
  1: [('/home/keyi/workspace/kratos/tests/test_generator.py', 532)],
  2: [('/home/keyi/workspace/kratos/tests/test_generator.py', 534)],
  3: [('/home/keyi/workspace/kratos/tests/test_generator.py', 535)],
  6: [('/home/keyi/workspace/kratos/tests/test_generator.py', 539),
      ('/home/keyi/workspace/kratos/src/expr.cc', 455),
      ('/home/keyi/workspace/kratos/tests/test_generator.py', 541),
      ('/home/keyi/workspace/kratos/src/expr.cc', 485),
      ('/home/keyi/workspace/kratos/src/pass.cc', 653)]
}

These pass.cc is the pass that removed the pass through module.

If we modified the source code a little bit that change the wire assignment into a combination block, such as

class Top(Generator):
    def __init__(self):
        super().__init__("top", True)

        self.input("in", 1)
        self.output("out", 1)

        pass_through = PassThroughMod()
        self.add_child_generator("pass", pass_through)
        self.wire(self["pass"].ports["in"], self.ports["in"])

        self.add_code(self.code_block)

    def code_block(self):
        self.ports.out = self["pass"].ports.out

We can see the generated verilog will be a little bit verbose:

module top (
  input logic  in,
  output logic  out
);

logic   top$in_0;
assign top$in_0 = in;
always_comb begin
  out = top$in_0;
end
endmodule   // top

And the debug info shows all the information as well:

{
  1: [('/home/keyi/workspace/kratos/tests/test_generator.py', 554)],
  2: [('/home/keyi/workspace/kratos/tests/test_generator.py', 556)],
  3: [('/home/keyi/workspace/kratos/tests/test_generator.py', 557)],
  7: [('/home/keyi/workspace/kratos/tests/test_generator.py', 561), ('/home/keyi/workspace/kratos/src/expr.cc', 455)],
  8: [('/home/keyi/workspace/kratos/tests/test_generator.py', 563)],
  9: [('/home/keyi/workspace/kratos/tests/test_generator.py', 566), ('/home/keyi/workspace/kratos/src/expr.cc', 485)]}

Ecosystem

Similar to Magma, kratos has its own ecosystem to program behavioral verilog in Python. They are named after sons of Titans in Greek mythology.

kratos is a programming model for building hardware. The main abstraction in kratos in a Generator. Generator can be modified at any time through passes.

zelus is a library of useful generators, such as mux and decoder. They are designed to be as efficient as possible.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

kratos-0.0.13-cp37-cp37m-manylinux1_x86_64.whl (1.3 MB view details)

Uploaded CPython 3.7m

kratos-0.0.13-cp37-cp37m-macosx_10_14_x86_64.whl (595.1 kB view details)

Uploaded CPython 3.7mmacOS 10.14+ x86-64

kratos-0.0.13-cp36-cp36m-manylinux1_x86_64.whl (1.3 MB view details)

Uploaded CPython 3.6m

kratos-0.0.13-cp35-cp35m-manylinux1_x86_64.whl (1.3 MB view details)

Uploaded CPython 3.5m

File details

Details for the file kratos-0.0.13-cp37-cp37m-manylinux1_x86_64.whl.

File metadata

  • Download URL: kratos-0.0.13-cp37-cp37m-manylinux1_x86_64.whl
  • Upload date:
  • Size: 1.3 MB
  • Tags: CPython 3.7m
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.13.0 pkginfo/1.5.0.1 requests/2.22.0 setuptools/41.0.1 requests-toolbelt/0.9.1 tqdm/4.32.2 CPython/3.7.3

File hashes

Hashes for kratos-0.0.13-cp37-cp37m-manylinux1_x86_64.whl
Algorithm Hash digest
SHA256 56abe26cfcbde0e2cc4aae739eac970501c2d88be8541e8dc29bc2e4fc7333d2
MD5 9b85f0e107e96c6dc8bddaff4300ceaf
BLAKE2b-256 20b04e554a1ea70174b066b703b1687eb23d62ab7856420ec04422888308a1f6

See more details on using hashes here.

File details

Details for the file kratos-0.0.13-cp37-cp37m-macosx_10_14_x86_64.whl.

File metadata

  • Download URL: kratos-0.0.13-cp37-cp37m-macosx_10_14_x86_64.whl
  • Upload date:
  • Size: 595.1 kB
  • Tags: CPython 3.7m, macOS 10.14+ x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.13.0 pkginfo/1.5.0.1 requests/2.22.0 setuptools/39.0.1 requests-toolbelt/0.9.1 tqdm/4.33.0 CPython/3.7.0

File hashes

Hashes for kratos-0.0.13-cp37-cp37m-macosx_10_14_x86_64.whl
Algorithm Hash digest
SHA256 74cd989988817b803e7b969f6fd68ee77fda29475ffc46aae5e3fbb548e740b8
MD5 bb40cc4d503d4f4ad3181a63dfeb45f3
BLAKE2b-256 6b4705b8ce3bbf9505df54d33aeecbe580bb785a672b1ed5bbc7ffb745767d4b

See more details on using hashes here.

File details

Details for the file kratos-0.0.13-cp36-cp36m-manylinux1_x86_64.whl.

File metadata

  • Download URL: kratos-0.0.13-cp36-cp36m-manylinux1_x86_64.whl
  • Upload date:
  • Size: 1.3 MB
  • Tags: CPython 3.6m
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.13.0 pkginfo/1.5.0.1 requests/2.22.0 setuptools/41.0.1 requests-toolbelt/0.9.1 tqdm/4.32.2 CPython/3.7.3

File hashes

Hashes for kratos-0.0.13-cp36-cp36m-manylinux1_x86_64.whl
Algorithm Hash digest
SHA256 e85881789b3de8e5c70426a9c3203316679a2726332fe2504127e85fbfb5119c
MD5 df46d3faa09a0984a2d07d720446dce8
BLAKE2b-256 f2d8a6ee0911e39a5ad4eb2c5344e6916f0fb29a2e339a1f27cf7cc4e9fed73d

See more details on using hashes here.

File details

Details for the file kratos-0.0.13-cp35-cp35m-manylinux1_x86_64.whl.

File metadata

  • Download URL: kratos-0.0.13-cp35-cp35m-manylinux1_x86_64.whl
  • Upload date:
  • Size: 1.3 MB
  • Tags: CPython 3.5m
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.13.0 pkginfo/1.5.0.1 requests/2.22.0 setuptools/41.0.1 requests-toolbelt/0.9.1 tqdm/4.32.2 CPython/3.7.3

File hashes

Hashes for kratos-0.0.13-cp35-cp35m-manylinux1_x86_64.whl
Algorithm Hash digest
SHA256 01a356df37a8d4f5c53d1fd21f74d36d72944cb653b4c50e31cb8df8a5591742
MD5 c2b70110dc0bd69f932a89d79c601fa4
BLAKE2b-256 28c15c23ee8af9a9f80545bb31aaeb410f13283279e72b8d6feae1be27d31604

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page