~cypheon/kicad2spice

ref: 96e390bc4f914314da98ecdfd7bd775e620563e2 kicad2spice/lib/export_spice.ml -rw-r--r-- 2.4 KiB
96e390bc — Johann Rudloff Implement correct pin order according to field "Spice_Node_Sequence" 3 years ago
                                                                                
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
open List

open Connectiongraph
open Schematic

let comp_ignored comp =
  comp.Comp.ref.[0] = '#'
  || Fields.get comp.Comp.fields Fields.Keys.spice_netlist_enabled "Y" <> "Y"

let make_cache kf vf xs =
  let tbl = Hashtbl.create (Enum.count xs) in
  Enum.iter (fun x ->
    Hashtbl.replace tbl (kf x) (vf x)
  ) xs;
  tbl

let id x = x

let comp_name comp =
  let comp_type_from_name = String.sub comp.Comp.ref 0 1 in
  let comp_type = Fields.get comp.Comp.fields Fields.Keys.spice_primitive comp_type_from_name in
  if comp_type_from_name = comp_type then comp.Comp.ref
  else comp_type ^ comp.Comp.ref

let make_unique used name =
  if not (Hashtbl.mem used name) then (Hashtbl.add used name 1; name)
  else begin
    let rec helper n =
      let full_name = name ^ "_" ^ (string_of_int n) in
      if not (Hashtbl.mem used full_name) then (Hashtbl.add used full_name 1; full_name)
      else helper (n+1)
    in helper 2
  end

let pin_order comp =
  let default_order = List.map Pin.number comp.Comp.part.CompDef.pins in
  Stdlib.Option.value ~default:default_order (
    Fields.find_opt Fields.Keys.spice_node_sequence comp.Comp.fields
    |> Stdlib.Option.map Lex_tokenize.tokenize
  )

let write_comp outch pin_cache comp name =
  let pins_in_order = List.map (Comp.find_pin comp) (pin_order comp) in
  let pin_nets = map (fun pin ->
    Hashtbl.find pin_cache (comp.Comp.ref, pin.Pin.number)
    ) pins_in_order in
  output_string outch name;
  output_string outch (" " ^ (String.concat " " pin_nets));
  output_string outch (" " ^ (comp.Comp.value));
  output_string outch "\n"

let write_netlist outch schematic netlist =
  let net_names = make_cache id ( fun net_name ->
    Netlist.driver_net_name netlist net_name
  ) (ExtHashtbl.Hashtbl.keys netlist.Netlist.nets) in
  let pin_cache = Hashtbl.create 512 in
  Hashtbl.iter ( fun net_name subgraph -> iter (
    function
      | Item.Pin (comp, pin) -> Hashtbl.replace pin_cache (comp.ref, pin.number) (Hashtbl.find net_names net_name)
      | _ -> failwith "invalid netlist"
  ) subgraph.Subgraph.items
  ) netlist.Netlist.nets;
  output_string outch ".title KiCad schematic (by eeschema2netlist)\n";
  let used_comp_names = Hashtbl.create 512 in
  iter ( function
    | Item.Comp comp when not (comp_ignored comp) ->
        let comp_export_name = make_unique used_comp_names (comp_name comp) in
        write_comp outch pin_cache comp comp_export_name
    | _ -> ()
  ) schematic.items;
  output_string outch ".end\n";
  ()