Merge 8428032d83 into 31d1850bc8
This commit is contained in:
commit
4f8323f27c
|
|
@ -21,3 +21,4 @@ Icarus Verilog. The code generator is selected by the "-t" command line flag.
|
|||
tgt-sizer
|
||||
tgt-verilog
|
||||
tgt-blif
|
||||
tgt-flow
|
||||
|
|
|
|||
|
|
@ -0,0 +1,99 @@
|
|||
The Flow Dataflow Exporter (-tflow)
|
||||
===================================
|
||||
|
||||
The flow code generator exports the elaborated design as a JSON
|
||||
*dataflow database* rather than a simulation or netlist artifact. The
|
||||
output describes the module hierarchy, the ports/parameters/signals of
|
||||
each module, and the dataflow graph (which processes and continuous
|
||||
assignments read and drive which nets), so that IDEs and analysis tools
|
||||
can render dataflow panels, browse the elaborated hierarchy, and trace
|
||||
input-to-output continuity across the design.
|
||||
|
||||
The emitted schema (``flowtracer1.verilog.v0``) is the Verilog companion
|
||||
to the GHDL ``--flow`` exporter (``flowtracer1.vhdl.v0``), so a single
|
||||
consumer works across Verilog (via this target) and VHDL (via GHDL)
|
||||
designs.
|
||||
|
||||
|
||||
USAGE
|
||||
-----
|
||||
|
||||
::
|
||||
|
||||
% iverilog -tflow -o<path>.flow <source files>...
|
||||
|
||||
The flow target runs at elaboration time; no simulation is performed.
|
||||
The root module of the elaborated design becomes the ``top`` of the
|
||||
exported database. Because the exporter reads the fully elaborated
|
||||
netlist, parameter values, generate blocks, and instance bindings are
|
||||
all resolved.
|
||||
|
||||
|
||||
OUTPUT
|
||||
------
|
||||
|
||||
The output is a single JSON object with these top-level fields:
|
||||
|
||||
``schema``
|
||||
Always ``"flowtracer1.verilog.v0"``.
|
||||
|
||||
``top``
|
||||
The basename of the root module instance.
|
||||
|
||||
``modules``
|
||||
One entry per module *type*, each with ``ports`` (name/direction/
|
||||
type), ``generics`` (parameters), ``signals``, the name-based
|
||||
``processes`` and ``assignments`` (with ``reads``/``drives``/
|
||||
``sensitivity`` given as signal names), and the ``instances`` it
|
||||
contains (with ``port_map`` and resolved ``generic_map``).
|
||||
|
||||
``hierarchy``
|
||||
The elaborated instance tree. Each node carries its ``port_map``
|
||||
(formal-to-actual associations resolved through the shared net) and
|
||||
``children``. Generate blocks appear as transparent frames marked
|
||||
``"scope": true`` with a ``generate`` object describing the kind
|
||||
(``for``/``if``), label, and index.
|
||||
|
||||
``nets`` and ``cells``
|
||||
A secondary, integer-id dataflow graph: ``nets`` are the canonical
|
||||
nexuses (with ``drivers``/``loads`` referring to cell ids) and
|
||||
``cells`` are the processes, gates, LPM devices, and constants (with
|
||||
``drives``/``reads`` referring to net ids, plus ``clocked`` and
|
||||
``clock_net``).
|
||||
|
||||
|
||||
POSITIONS
|
||||
---------
|
||||
|
||||
Every ``pos`` / ``inst_pos`` is a compact string of byte offsets,
|
||||
``"start:begin:end"``, to help source-scanning consumers (such as Perl
|
||||
lexers) locate constructs:
|
||||
|
||||
* *start* -- byte offset of the construct (first non-blank character of
|
||||
its line);
|
||||
* *begin* -- byte offset of the ``begin`` keyword that opens a
|
||||
procedural or generate block -- empty when there is none;
|
||||
* *end* -- byte offset of the closing ``end``/``endmodule`` keyword or
|
||||
the terminating ``;`` -- empty for a plain point.
|
||||
|
||||
So a port or signal is ``"start::"``, a module is ``"start::end"``
|
||||
(``module`` .. ``endmodule``), an instance is ``"start::end"`` (.. ``;``),
|
||||
and an ``always``/``initial`` block or generate frame is
|
||||
``"start:begin:end"``. Because the ``ivl_target`` API exposes only line
|
||||
numbers, the exporter reads the source files and scans them (comment- and
|
||||
string-aware) to recover these byte offsets and spans.
|
||||
|
||||
|
||||
LIMITATIONS
|
||||
-----------
|
||||
|
||||
Continuity through bit- and part-selects (for example a generate that
|
||||
connects ``.d(bus[i])``) is not yet represented at the individual-bit
|
||||
level; whole-signal connections are tracked.
|
||||
|
||||
For a process sensitive to several edges (for example an
|
||||
asynchronous-reset flip-flop ``@(posedge clk or posedge rst)``), the
|
||||
``clock_net`` field reports the first edge signal.
|
||||
|
||||
Constant tie-offs and synthetic compiler temporaries are summarized
|
||||
rather than reported individually.
|
||||
|
|
@ -40,7 +40,7 @@ VERSION_MAJOR = @VERSION_MAJOR@
|
|||
VERSION_MINOR = @VERSION_MINOR@
|
||||
|
||||
SUBDIRS = ivlpp vhdlpp vvp vpi tgt-null tgt-stub tgt-vvp \
|
||||
tgt-vhdl tgt-vlog95 tgt-pcb tgt-blif tgt-sizer driver \
|
||||
tgt-vhdl tgt-vlog95 tgt-pcb tgt-blif tgt-sizer tgt-flow driver \
|
||||
ivtest
|
||||
# Only run distclean for these directories.
|
||||
NOTUSED = tgt-fpga tgt-pal tgt-verilog
|
||||
|
|
|
|||
|
|
@ -453,6 +453,7 @@ AC_CONFIG_FILES([
|
|||
ivtest/Makefile
|
||||
libveriuser/Makefile
|
||||
tgt-blif/Makefile
|
||||
tgt-flow/Makefile
|
||||
tgt-fpga/Makefile
|
||||
tgt-null/Makefile
|
||||
tgt-pal/Makefile
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
# Test list for the flow (-tflow) dataflow exporter target.
|
||||
#
|
||||
# Each entry names a Verilog source under flow/<name>.v. The runner
|
||||
# flow_reg.py compiles it with `iverilog -tflow`, parses the resulting
|
||||
# .flow JSON, and checks structural expectations (schema, hierarchy,
|
||||
# processes/assignments, generate frames). Run with: python3 flow_reg.py
|
||||
#
|
||||
flow_basic
|
||||
flow_comb
|
||||
flow_generate
|
||||
flow_genpath
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
*.flow
|
||||
*.log
|
||||
log/
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
// Phase 0 test design: a counter instantiated inside a top module,
|
||||
// to exercise scope hierarchy + nexus reachability in tgt-flow.
|
||||
|
||||
module counter #(parameter WIDTH = 4) (
|
||||
input wire clk,
|
||||
input wire rst,
|
||||
input wire en,
|
||||
output reg [WIDTH-1:0] count
|
||||
);
|
||||
always @(posedge clk or posedge rst) begin
|
||||
if (rst)
|
||||
count <= {WIDTH{1'b0}};
|
||||
else if (en)
|
||||
count <= count + 1'b1;
|
||||
end
|
||||
endmodule
|
||||
|
||||
module top (
|
||||
input wire clk,
|
||||
input wire rst,
|
||||
output wire [3:0] q
|
||||
);
|
||||
wire enable = 1'b1;
|
||||
counter #(.WIDTH(4)) u_cnt (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.en (enable),
|
||||
.count (q)
|
||||
);
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
// Richer Phase 2 test: comb always with case, ternary, continuous
|
||||
// assign, and two levels of hierarchy.
|
||||
|
||||
module alu (
|
||||
input wire [1:0] op,
|
||||
input wire [7:0] a,
|
||||
input wire [7:0] b,
|
||||
output reg [7:0] y
|
||||
);
|
||||
always @(*) begin
|
||||
case (op)
|
||||
2'b00: y = a + b;
|
||||
2'b01: y = a - b;
|
||||
2'b10: y = a & b;
|
||||
default: y = a ^ b;
|
||||
endcase
|
||||
end
|
||||
endmodule
|
||||
|
||||
module datapath (
|
||||
input wire [1:0] sel,
|
||||
input wire [7:0] x,
|
||||
input wire [7:0] z,
|
||||
output wire [7:0] result,
|
||||
output wire is_zero
|
||||
);
|
||||
wire [7:0] alu_out;
|
||||
alu u_alu (.op(sel), .a(x), .b(z), .y(alu_out));
|
||||
assign result = alu_out;
|
||||
assign is_zero = (alu_out == 8'b0) ? 1'b1 : 1'b0;
|
||||
endmodule
|
||||
|
||||
module chip (
|
||||
input wire [1:0] mode,
|
||||
input wire [7:0] in0,
|
||||
input wire [7:0] in1,
|
||||
output wire [7:0] out,
|
||||
output wire zero
|
||||
);
|
||||
datapath u_dp (
|
||||
.sel (mode),
|
||||
.x (in0),
|
||||
.z (in1),
|
||||
.result (out),
|
||||
.is_zero(zero)
|
||||
);
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
// Phase 3 test: for-generate replicating a sub-module, plus an
|
||||
// if-generate, to exercise generate-frame emission.
|
||||
|
||||
module inv #(parameter ID = 0) (
|
||||
input wire d,
|
||||
output wire q
|
||||
);
|
||||
assign q = ~d;
|
||||
endmodule
|
||||
|
||||
module gen_top #(parameter N = 3) (
|
||||
input wire [2:0] din,
|
||||
output wire [2:0] dout
|
||||
);
|
||||
genvar i;
|
||||
generate
|
||||
for (i = 0; i < 3; i = i + 1) begin : row
|
||||
inv #(.ID(i)) u_cell (.d(din[i]), .q(dout[i]));
|
||||
end
|
||||
endgenerate
|
||||
|
||||
generate
|
||||
if (N > 0) begin : opt
|
||||
wire tap;
|
||||
assign tap = din[0];
|
||||
end
|
||||
endgenerate
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
// Generate frame with WHOLE-signal port connections (isolates frame
|
||||
// transparency from bit-select handling).
|
||||
module inv8 (input wire [7:0] d, output wire [7:0] q);
|
||||
assign q = ~d;
|
||||
endmodule
|
||||
|
||||
module wrap (input wire [7:0] din, output wire [7:0] dout);
|
||||
generate
|
||||
if (1) begin : blk
|
||||
inv8 u_inv (.d(din), .q(dout));
|
||||
end
|
||||
endgenerate
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,210 @@
|
|||
''' Regression runner for the flow (-tflow) dataflow exporter target.
|
||||
|
||||
For each test named in flow.list, this compiles flow/<name>.v with
|
||||
`iverilog -tflow` and validates the resulting flowtracer1.verilog.v0
|
||||
JSON: every output must be well-formed and carry the expected schema,
|
||||
a top, and a non-empty module/hierarchy set; per-test checks then
|
||||
assert the dataflow facts the exporter is meant to capture (clocked
|
||||
processes, port-map continuity, continuous-assign cone reads, and
|
||||
generate frames).
|
||||
|
||||
Run with: python3 flow_reg.py '''
|
||||
|
||||
import os
|
||||
import re
|
||||
import json
|
||||
import subprocess
|
||||
|
||||
# Name of the iverilog command. May vary in different installations.
|
||||
IVERILOG = "iverilog"
|
||||
|
||||
|
||||
def get_tests() -> list:
|
||||
'''Read the test names from flow.list (first word of each line).'''
|
||||
match_prog = re.compile(r"^([a-zA-Z0-9_.]+).*$")
|
||||
tests = []
|
||||
with open("flow.list", encoding='ascii') as fd:
|
||||
for line in fd:
|
||||
if line[0] == "#":
|
||||
continue
|
||||
match = match_prog.search(line)
|
||||
if match:
|
||||
tests.append(match.group(1))
|
||||
return tests
|
||||
|
||||
|
||||
# ---- per-test structural checks ----------------------------------------
|
||||
# Each returns (ok, message). `d` is the parsed .flow document.
|
||||
|
||||
def _module(d, name):
|
||||
for m in d["modules"]:
|
||||
if m["name"] == name:
|
||||
return m
|
||||
return None
|
||||
|
||||
|
||||
def _find_in_hier(d, pred):
|
||||
'''Depth-first search of hierarchy[] for a node matching pred.'''
|
||||
stack = list(d["hierarchy"])
|
||||
while stack:
|
||||
n = stack.pop()
|
||||
if pred(n):
|
||||
return n
|
||||
stack.extend(n.get("children", []))
|
||||
return None
|
||||
|
||||
|
||||
def check_basic(d):
|
||||
if d["top"] != "top":
|
||||
return False, "top != 'top'"
|
||||
cnt = _module(d, "counter")
|
||||
if not cnt:
|
||||
return False, "no 'counter' module"
|
||||
proc = [p for p in cnt["processes"]
|
||||
if "count" in p["drives"] and p.get("sensitivity")]
|
||||
if not proc:
|
||||
return False, "no clocked process driving count"
|
||||
# port_map continuity: u_cnt.count maps to parent net q
|
||||
node = _find_in_hier(d, lambda n: n.get("module") == "counter")
|
||||
if not node:
|
||||
return False, "counter instance not in hierarchy"
|
||||
pm = {a["formal"]: a["actuals"] for a in node["port_map"]}
|
||||
if "q" not in pm.get("count", []):
|
||||
return False, "port_map count->q missing"
|
||||
return True, "clocked process + port_map ok"
|
||||
|
||||
|
||||
def check_comb(d):
|
||||
if d["top"] != "chip":
|
||||
return False, "top != 'chip'"
|
||||
dp = _module(d, "datapath")
|
||||
if not dp:
|
||||
return False, "no 'datapath' module"
|
||||
res = [a for a in dp["assignments"]
|
||||
if a["target"] == "result" and "alu_out" in a["reads"]]
|
||||
if not res:
|
||||
return False, "assign result<-alu_out (cone) missing"
|
||||
return True, "continuous-assign cone read ok"
|
||||
|
||||
|
||||
def check_generate(d):
|
||||
frame = _find_in_hier(d, lambda n: n.get("scope") is True
|
||||
and "generate" in n)
|
||||
if not frame:
|
||||
return False, "no generate frame in hierarchy"
|
||||
kind = frame["generate"].get("kind")
|
||||
if kind not in ("for", "if"):
|
||||
return False, "generate.kind not for/if"
|
||||
return True, "generate frame ({}) ok".format(kind)
|
||||
|
||||
|
||||
def check_genpath(d):
|
||||
# if-generate with whole-signal connection: the instance under the
|
||||
# frame must resolve its actuals to the parent nets.
|
||||
inst = _find_in_hier(d, lambda n: n.get("module") == "inv8")
|
||||
if not inst:
|
||||
return False, "inv8 instance not found under frame"
|
||||
pm = {a["formal"]: a["actuals"] for a in inst["port_map"]}
|
||||
if "din" not in pm.get("d", []) or "dout" not in pm.get("q", []):
|
||||
return False, "port_map through frame not resolved"
|
||||
return True, "generate-frame port_map ok"
|
||||
|
||||
|
||||
CHECKS = {
|
||||
"flow_basic": check_basic,
|
||||
"flow_comb": check_comb,
|
||||
"flow_generate": check_generate,
|
||||
"flow_genpath": check_genpath,
|
||||
}
|
||||
|
||||
|
||||
def run_test(test_name: str) -> bool:
|
||||
'''Compile one test with -tflow and validate its JSON.'''
|
||||
src = "flow/" + test_name + ".v"
|
||||
out = "flow/" + test_name + ".flow"
|
||||
|
||||
cmd = IVERILOG + " -g2012 -tflow -o" + out + " " + src
|
||||
rc = subprocess.call(cmd + " > log/" + test_name + ".log 2>&1", shell=True)
|
||||
if rc != 0:
|
||||
return False
|
||||
|
||||
try:
|
||||
with open(out, encoding='ascii') as fd:
|
||||
doc = json.load(fd)
|
||||
except (OSError, ValueError):
|
||||
return False
|
||||
|
||||
# Invariants common to every well-formed output.
|
||||
if doc.get("schema") != "flowtracer1.verilog.v0":
|
||||
return False
|
||||
if not doc.get("top") or not doc.get("modules") or not doc.get("hierarchy"):
|
||||
return False
|
||||
# Every position is the compact "start:begin:end" byte-offset string.
|
||||
if not _positions_well_formed(doc):
|
||||
return False
|
||||
|
||||
check = CHECKS.get(test_name)
|
||||
if check:
|
||||
ok, _msg = check(doc)
|
||||
return ok
|
||||
return True
|
||||
|
||||
|
||||
_POS_RE = re.compile(r"^[0-9]*:[0-9]*:[0-9]*$")
|
||||
|
||||
|
||||
def _positions_well_formed(node) -> bool:
|
||||
'''Every "pos"/"inst_pos" value, anywhere in the document, must be the
|
||||
compact "start:begin:end" byte-offset string (parts may be empty).'''
|
||||
if isinstance(node, dict):
|
||||
for key, val in node.items():
|
||||
if key in ("pos", "inst_pos"):
|
||||
if not (isinstance(val, str) and _POS_RE.match(val)):
|
||||
return False
|
||||
elif not _positions_well_formed(val):
|
||||
return False
|
||||
return True
|
||||
if isinstance(node, list):
|
||||
return all(_positions_well_formed(x) for x in node)
|
||||
return True
|
||||
|
||||
|
||||
def get_ivl_version() -> list:
|
||||
'''Get the iverilog version.'''
|
||||
text = subprocess.check_output([IVERILOG, "-V"])
|
||||
match = re.search(b'Icarus Verilog version ([0-9]+)\\.([0-9]+)', text)
|
||||
if not match:
|
||||
return None
|
||||
items = match.groups()
|
||||
return [str(items[0], 'ascii'), str(items[1], 'ascii')]
|
||||
|
||||
|
||||
def run_tests(tests: list):
|
||||
'''Run all tests in the list.'''
|
||||
ivl_ver = get_ivl_version()
|
||||
print("Running flow tests for Icarus Verilog version: {}.{}".format(
|
||||
ivl_ver[0], ivl_ver[1]))
|
||||
print("=" * 50)
|
||||
|
||||
if not os.path.exists("log"):
|
||||
os.mkdir("log")
|
||||
|
||||
count_passed = 0
|
||||
count_failed = 0
|
||||
width = max(len(name) for name in tests)
|
||||
for test in tests:
|
||||
passed = run_test(test)
|
||||
if passed:
|
||||
count_passed += 1
|
||||
res = "Passed"
|
||||
else:
|
||||
count_failed += 1
|
||||
res = "Failed"
|
||||
print("{name:>{width}}: {res}.".format(name=test, width=width, res=res))
|
||||
|
||||
print("=" * 50)
|
||||
print("Tests results: Passed {}, Failed {}".format(count_passed, count_failed))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
run_tests(get_tests())
|
||||
|
|
@ -0,0 +1,106 @@
|
|||
#
|
||||
# This source code is free software; you can redistribute it
|
||||
# and/or modify it in source code form under the terms of the GNU
|
||||
# Library General Public License as published by the Free Software
|
||||
# Foundation; either version 2 of the License, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Library General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Library General Public
|
||||
# License along with this program; if not, write to the Free
|
||||
# Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
# Boston, MA 02110-1301, USA.
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
|
||||
suffix = @install_suffix@
|
||||
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
srcdir = @srcdir@
|
||||
|
||||
VPATH = $(srcdir)
|
||||
|
||||
bindir = @bindir@
|
||||
libdir = @libdir@
|
||||
includedir = $(prefix)/include
|
||||
|
||||
CC = @CC@
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
|
||||
ifeq (@srcdir@,.)
|
||||
INCLUDE_PATH = -I. -I..
|
||||
else
|
||||
INCLUDE_PATH = -I. -I.. -I$(srcdir) -I$(srcdir)/..
|
||||
endif
|
||||
|
||||
CPPFLAGS = $(INCLUDE_PATH) @CPPFLAGS@ @DEFS@ @PICFLAG@
|
||||
CFLAGS = @WARNING_FLAGS@ @WARNING_FLAGS_CC@ @CFLAGS@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
|
||||
O = flow.o
|
||||
|
||||
all: dep flow.tgt
|
||||
|
||||
check: all
|
||||
|
||||
clean:
|
||||
rm -rf *.o dep flow.tgt
|
||||
|
||||
distclean: clean
|
||||
rm -f Makefile config.log
|
||||
|
||||
cppcheck: $(O:.o=.c)
|
||||
cppcheck --enable=all --std=c99 --std=c++11 -f \
|
||||
--check-level=exhaustive \
|
||||
--suppressions-list=$(srcdir)/../cppcheck-global.sup \
|
||||
--relative-paths=$(srcdir) $(INCLUDE_PATH) $^
|
||||
|
||||
Makefile: $(srcdir)/Makefile.in ../config.status
|
||||
cd ..; ./config.status --file=tgt-flow/$@
|
||||
|
||||
dep:
|
||||
mkdir dep
|
||||
|
||||
%.o: %.c | dep
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) @DEPENDENCY_FLAG@ -c $< -o $*.o
|
||||
mv $*.d dep
|
||||
|
||||
ifeq (@WIN32@,yes)
|
||||
TGTLDFLAGS=-L.. -livl
|
||||
TGTDEPLIBS=../libivl.a
|
||||
else
|
||||
TGTLDFLAGS=
|
||||
TGTDEPLIBS=
|
||||
endif
|
||||
|
||||
flow.tgt: $O $(TGTDEPLIBS)
|
||||
$(CC) @shared@ $(LDFLAGS) -o $@ $O $(TGTLDFLAGS)
|
||||
|
||||
install: all installdirs installfiles
|
||||
|
||||
F = ./flow.tgt \
|
||||
$(srcdir)/flow.conf \
|
||||
$(srcdir)/flow-s.conf
|
||||
|
||||
installfiles: $(F) | installdirs
|
||||
$(INSTALL_PROGRAM) ./flow.tgt "$(DESTDIR)$(libdir)/ivl$(suffix)/flow.tgt"
|
||||
$(INSTALL_DATA) $(srcdir)/flow.conf "$(DESTDIR)$(libdir)/ivl$(suffix)/flow.conf"
|
||||
$(INSTALL_DATA) $(srcdir)/flow-s.conf "$(DESTDIR)$(libdir)/ivl$(suffix)/flow-s.conf"
|
||||
|
||||
installdirs: $(srcdir)/../mkinstalldirs
|
||||
$(srcdir)/../mkinstalldirs "$(DESTDIR)$(libdir)/ivl$(suffix)"
|
||||
|
||||
uninstall:
|
||||
rm -f "$(DESTDIR)$(libdir)/ivl$(suffix)/flow.tgt"
|
||||
rm -f "$(DESTDIR)$(libdir)/ivl$(suffix)/flow.conf"
|
||||
rm -f "$(DESTDIR)$(libdir)/ivl$(suffix)/flow-s.conf"
|
||||
|
||||
|
||||
-include $(patsubst %.o, dep/%.d, $O)
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
functor:synth2
|
||||
functor:synth
|
||||
functor:syn-rules
|
||||
functor:cprop
|
||||
functor:nodangle
|
||||
flag:DLL=flow.tgt
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,3 @@
|
|||
functor:cprop
|
||||
functor:nodangle
|
||||
flag:DLL=flow.tgt
|
||||
Loading…
Reference in New Issue