Coder Social home page Coder Social logo

ujamjar / hardcaml Goto Github PK

View Code? Open in Web Editor NEW
118.0 118.0 7.0 10.53 MB

[Deprecated see github.com/janestreet/hardcaml] Register Transfer Level Hardware Design in OCaml

Home Page: https://github.com/janestreet/hardcaml

License: ISC License

Shell 0.10% OCaml 74.55% Tcl 0.04% Verilog 0.03% Jupyter Notebook 24.89% Makefile 0.05% CSS 0.34%

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

hardcaml's Issues

Interface: signal width not checked in output signal assignation

Considering the code below:

open HardCaml
open Signal.Comb
open Signal.Seq

module T_in = struct
  type 'a t = {
    sig_0 : 'a;
  } [@@deriving hardcaml { rtlmangle = true; rtlsuffix = "_in"; } ]
end

module T_out = struct
  type 'a t = {
    sig_0 : 'a [@bits 64];
  } [@@deriving hardcaml { rtlmangle = true; rtlsuffix = "_out"; } ]
end

let build i =
  let open T_in in
  let some_value = reg_fb r_async i.sig_0 8 (fun v -> (consti 8 0)) in
  some_value

let make i =
  let sig_0 = build i in
  T_out.({ sig_0; })

module Builder = Interface.Circ(T_in)(T_out)

let () =
  let circ = Builder.make "bad_signal" make in
  Rtl.Verilog.write (output_string stdout) circ

The following is generated without error:

module bad_signal (
    sig_0_in,
    reset,
    clock,
    sig_0_out
);

    input sig_0_in;
    input reset;
    input clock;
    output [7:0] sig_0_out;

    /* signal declarations */
    wire [7:0] _39 = 8'b00000000;
    wire vdd = 1'b1;
    wire [7:0] _40 = 8'b00000000;
    wire [7:0] _42 = 8'b00000000;
    wire [7:0] _38;
    reg [7:0] _41;

    /* logic */
    assign _38 = _42;
    always @(posedge clock or posedge reset) begin
        if (reset)
            _41 <= _40;
        else
            if (sig_0_in)
                _41 <= _38;
    end

    /* aliases */

    /* output assignments */
    assign sig_0_out = _41;

endmodule

The [@bits 64] attribute of T_out.sig_0 is ignored as the generated sig_0_out output signal is wrongly sized [7:0]. I was expecting a "mismatched signal size in assignment" kind of error.

The guarded API is excellent

That's all ๐Ÿ‘ I'll explore soon the possibility to make the syntax more OCaml-y in ppx_hardcaml, with things like maybe match%hw.guard, if%hw.guard, etc.

Example for using Verilog parameters

While perusing the code generation part of the framework I stumbled on the part handling generic statements. Is this related to parameter in Verilog ? Is there any example on how to use them ?

Add arrays to recipe module

Neat though it is, it's not actually all that useful without array support.

Some difficulty in providing optimal write (onehot or comparators for the enables) and read (mux sharing in presence of par) logic, but getting it working generally doesn't look too hard.

Complex top level example

Is there by any chance an example of a HardCaml top level that combines multiple HardCaml components altogether ? I am especially curious to know how "interfaces" can be exported given that the "interface" extension does not work in an .mli AFAICT.

$== precedence over |: operator

I've noticed that $== seems to take precedence over |::

some_sig $== a |:b;

Requires (a |: b) to work. According to the OCaml precedence rules that sort of makes sense as both $ and | have the same priority.

Maybe it would make sense to use <-: instead ?

simulation semantics (again)

We've tried 2 different semantics for the simulator;

  1. comb -> seq
  2. comb -> seq -> comb

The problem isn't the correctness of the simulation as such but what values you can read on the outputs after a simulation step

for ...
   set inputs;
   cycle sim;
   read outputs;

with (1) we read outputs computed from the old register state and inputs while with (2) we read outputs computed from the new register state and inputs.

The real problem actually relates more to the set inputs stage - sometimes we need to read an output in order to set an input and the exact output value you want to read depends on the waveform you are trying to set up. For example;

  1. Drive a request line on the same cycle the hardware generates a ready you need (2)
  2. Remove a request given a grant combinatorially generated by a priority driven round robin arbiter you need (1)

(to some extent these are implementation specific issues depending on where combinational logic is relative to registers and any feedback loops, but we need some way to deal with them)

To some extent this can already be worked around;

for ...
   set inputs;
   cycle_comb0 sim;
   cycle_seq sim;
   read outputs computed from old register values;
   cycle_comb1 sim;
   read outputs computed from new register values;

This does complicate matters though. I think an overall better way would be to provide the output ports computed both ways.

The standard outputs would revert to the old update method. When we need an output computed from the next state it can be computed on demand. For the higher level wrappers we could return output ports as an object with cur and next methods.

investigate cocotb

https://github.com/potentialventures/cocotb - provides an elegant coroutine based interface to verilog models for testbenches.

  • GPI interface abstracts VPI/VHPI for various simulators and VHDL+Verilog
  • Provides a bunch of abstract bus functional style models for various busses/protocols
  • Randomised testing libraries
  • Doesn't require a testbench shim layer

Downside; seems to require quite a complex scheduler to interact with the simulator properly. This would need careful investigation.

Building a simple combinatorial A/B arbitrator

I am trying to build a very simple module that looks like this:

module In = struct
  type 'a t = {
    rsa_i : 'a Result.t;
    rsb_i : 'a Result.t;
  } [@@deriving hardcaml]
end

module Out = struct
  type 'a t = {
    res_o  :'a Result.t;
  } [@@deriving hardcaml]
end

The Result interface looks like this:

module Result = struct
  type 'a t = {
    rs_vld : 'a [@bits  1];
    rs_len : 'a [@bits 16];
    rs_seq : 'a [@bits 32];
    rs_sts : 'a [@bits 64];
    rs_mln : 'a [@bits 16];
    rs_tts : 'a [@bits 64];
    rs_cnt : 'a [@bits  8];
    rs_prc : 'a [@bits 64];
    rs_qty : 'a [@bits 32];
  } [@@deriving hardcaml]
end

The purpose of that module is to select the proper input depending on their rs_seq sequence number. My initial intuition was to simply compare them and return the complete interface as an output, but that does not seem possible as mux2 only manipulate signals.

Would you have any insight on returning a whole bunch of signals based on a signal condition ? The corresponding verily would look like this:

always @(*)
begin
  if (rsa_rs_seq > rsb_rs_seq)
  begin
    res_rs_vld <= rsa_rs_seq;
    ...
  end
  else
  begin
      res_rs_vld <= rsb_rs_seq;
    ...
  end
end

How to use waveterm

Hello Andy,

I have created a simple Hardcaml project and would like to simulate it using waveterm ex iPython notebook. I have a circuit that I can generate via "HardCaml.Rtl.Verilog.write (output_string stdout) circuit" and I can verify its functionality using shallow embedding and bit lists as well as compile the Verilog through to a netlist. My present cicruit is purely combinatorial logic but once I proceed to sequential logic I will need to simulate. So how do I go from here to using waveterm? From looking at the code I need to generate .wave files. My ultimate goal is to create the wave output in ASCII such that I can construct test cases comparing output against known values.

Thanks and best Regards

Chris Kohlhepp

Hierarchy support in simulation

What is the rationale for not supporting hierarchy in simulation ? It would be nice to be able to produce VCDs with nice, hierarchical set of signals.

dont generate dangling wires

Various unused constants are generated in the rtl.

These all, I think, relate to different register configurations (ie no reset, or clear)

Support unknowns

To allow synthesis more optimization opportunities.

Considering adding constu "11--0" and maybe umux (with default u's). Something like casex/casez might also be required, along with support for parallel_case/full_case.

Then need to figure out what to do in simulation which will need to model multi-value logic.

Testsuite

Implement a decent test-suite - runnable on the Travis-CI.

  • HardCaml.Bits API's among each other
  • HardCaml.Bits.Raw.Comb API against other bits APIs
  • Cyclesim + CyclesimRaw
  • Generated Verilog is compilable (via iverilog?)
  • Generated VHDL is compilable (via ghdl?)
  • Hierarchy tests

TO BE UPDATED.

Moving from ocamlp4 to PPX

It would make the integration to tools like Merlin possible. Have you considered it ? If not, I can give it a shot. Starting with the interface and subscript .[] extensions should not be too difficult. Although that would imply a slight syntax change.

Tracing internal signals

Hello,

Is there a way to get the VCD wrapper to generate also internal signals, and not just Input/Output signals ? I looked at the code of the wrapper, and it seems that it is already scanning for internal signals. However, I don't seem to get them added in my VCD.

Thanks,

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.