ujamjar / hardcaml Goto Github PK
View Code? Open in Web Editor NEW[Deprecated see github.com/janestreet/hardcaml] Register Transfer Level Hardware Design in OCaml
Home Page: https://github.com/janestreet/hardcaml
License: ISC License
[Deprecated see github.com/janestreet/hardcaml] Register Transfer Level Hardware Design in OCaml
Home Page: https://github.com/janestreet/hardcaml
License: ISC License
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.
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.
I will need to use two different clock domains in my design. Is there a way to explicitly instantiate/bind two different clock source in the simulator ?
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 ?
The title says it all :) Tiny example:
my_module
the_my_module
( .dat_out(_1782[78:15]), .mdl_out(_1782[14:12]), .ctl_out(_1782[11:4]), .err_out(_1782[3:3]), .eob_out(_1782[2:2]), .sob_out(_1782[1:1]), .vld_out(_1782[0:0]) );
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.
cause run time error while generating rtl. should be caught when creating the instantiation
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.
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 ?
We've tried 2 different semantics for the simulator;
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;
(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.
https://github.com/potentialventures/cocotb - provides an elegant coroutine based interface to verilog models for testbenches.
Downside; seems to require quite a complex scheduler to interact with the simulator properly. This would need careful investigation.
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
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
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.
Although this intuitively makes sense, it makes it complicated when using pre-defined interfaces like Avalon-ST. Output might also be optimized out, I did not check that part.
...for super fast simulation.
It would be nice to have a partition operation on signals, for instance:
val slice : t -> int -> t list
Various unused constants are generated in the rtl.
These all, I think, relate to different register configurations (ie no reset, or clear)
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.
It's highly likely that I'm doing something wrong, but I am unable to use the HardCaml.Syntax extension, as shown in the following screenshot.
Because of this I am also unable to follow the tutorial here (http://www.ujamjar.com/hardcaml/simulation.html).
Thanks in Advance.
Implement a decent test-suite - runnable on the Travis-CI.
TO BE UPDATED.
see #10
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.
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,
I have a module which number of instances is parameterized and greater than one. When I name one of its signal using (--)
the same name is used in all instances and therefore conflict with one another.
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.