package hardcaml_waveterm

  1. Overview
  2. Docs
Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source

Source file hardcaml_waveterm_cyclesim.ml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
open Base
open Hardcaml
module Node = Cyclesim.Node
module Traced = Cyclesim.Traced
module Data = Hardcaml.Wave_data
open Hardcaml_waveterm_kernel
include Expert.Make (Data)

let lookup_node sim cycle (t : Traced.internal_signal) =
  let width = Signal.width t.signal in
  let data = Data.create width in
  let v = Cyclesim.lookup_node_or_reg sim t in
  Option.map v ~f:(fun v ->
    let d = Node.data v in
    let byte_address = Node.byte_address v in
    let set_from_bytes = Data.set_from_bytes width in
    data, fun _ -> set_from_bytes data !cycle d byte_address)
;;

let lookup_port find_port sim cycle (t : Traced.io_port) =
  let width = Signal.width t.signal in
  let data = Data.create width in
  let v = find_port sim t.name in
  data, fun _ -> Data.set data !cycle !v
;;

let lookup_in_port sim cycle t = lookup_port Cyclesim.in_port sim cycle t

let lookup_out_port sim cycle t =
  lookup_port (Cyclesim.out_port ~clock_edge:Before) sim cycle t
;;

let create_wave signal name data =
  let width = Signal.width signal in
  let wave_format = Signal.Type.get_wave_format signal in
  let wave =
    if width = 1
       &&
       match wave_format with
       | Bit | Bit_or _ -> true
       | _ -> false
    then Wave.Binary (name, data)
    else Wave.Data (name, data, wave_format, Left)
  in
  wave
;;

let is_clock = function
  | "clock" | "clk" -> true
  | _ -> false
;;

let is_reset = function
  | "reset" | "rst" -> true
  | _ -> false
;;

let trace sim cycle =
  let traced = Cyclesim.traced sim in
  let io_port lookup (t : Traced.io_port) =
    if is_clock t.name
    then Wave.Clock t.name, fun _ -> ()
    else if is_reset t.name
    then (
      let data, _ = lookup sim cycle t in
      ( create_wave t.signal t.name data
      , fun v -> Data.set data !cycle (if v then Bits.vdd else Bits.gnd) ))
    else (
      let data, update = lookup sim cycle t in
      create_wave t.signal t.name data, update)
  in
  let internal_signal (t : Traced.internal_signal) =
    Option.value_map (lookup_node sim cycle t) ~default:[] ~f:(fun (data, update) ->
      List.map t.mangled_names ~f:(fun name ->
        if is_clock name
        then Wave.Clock name, fun _ -> ()
        else create_wave t.signal name data, update))
  in
  List.concat
    [ List.map traced.input_ports ~f:(io_port lookup_in_port)
    ; List.map traced.output_ports ~f:(io_port lookup_out_port)
    ; List.map traced.internal_signals ~f:internal_signal |> List.concat
    ]
;;

module Expert = struct
  let wrap sim =
    let cycle = ref 0 in
    let traced = trace sim cycle in
    let waves =
      let waves = Array.of_list_map traced ~f:fst in
      Array.sort waves ~compare:(fun w0 w1 ->
        String.compare (Wave.get_name w0) (Wave.get_name w1));
      waves
    in
    let updates = Array.of_list_map traced ~f:snd in
    let tasks rst () =
      Array.iter ~f:(fun f -> f rst) updates;
      Int.incr cycle
    in
    let sim =
      Cyclesim.Private.modify
        sim
        [ After, Reset, tasks true; Before, At_clock_edge, tasks false ]
    in
    sim, waves
  ;;
end

module Waveform = struct
  include Waveform

  let create sim =
    let ports =
      let port type_ (port_name, s) =
        { Port.type_
        ; port_name = port_name |> Port_name.of_string
        ; width = Bits.width !s
        }
      in
      let traced_port type_ { Cyclesim.Traced.signal; mangled_names } =
        List.map mangled_names ~f:(fun name ->
          { Port.type_
          ; port_name = name |> Port_name.of_string
          ; width = Signal.width signal
          })
      in
      List.concat
        [ List.map (Cyclesim.in_ports sim) ~f:(port Input)
        ; List.map (Cyclesim.out_ports sim) ~f:(port Output)
        ; List.concat_map (Cyclesim.traced sim).internal_signals ~f:(traced_port Internal)
        ]
    in
    let sim, waves = Expert.wrap sim in
    Waveform.create_from_data ~waves:(Array.to_list waves) ~ports, sim
  ;;
end
OCaml

Innovation. Community. Security.