Skip to content

Commit ce6db1b

Browse files
authored
Merge branch 'main' into tutorial
2 parents 2ffedd2 + 61dd771 commit ce6db1b

File tree

149 files changed

+3417
-1315
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

149 files changed

+3417
-1315
lines changed

.clangd

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
Diagnostics:
2-
Suppress: bugprone-integer-division
2+
Suppress: bugprone-integer-division

.github/workflows/cmake-multi-platform.yml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,11 @@ jobs:
6969
# don't need to restrict these by OS or compiler as it's only source code that's being cached
7070
restore-keys: |
7171
${{ env.cache-name }}-
72-
72+
- name: Install Linux dependencies
73+
if: matrix.os == 'ubuntu-latest'
74+
run: |
75+
sudo apt-get update
76+
sudo apt-get install -y build-essential git make pkg-config cmake ninja-build gnome-desktop-testing libasound2-dev libpulse-dev libaudio-dev libfribidi-dev libjack-dev libsndio-dev libx11-dev libxext-dev libxrandr-dev libxcursor-dev libxfixes-dev libxi-dev libxss-dev libxtst-dev libxkbcommon-dev libdrm-dev libgbm-dev libgl1-mesa-dev libgles2-mesa-dev libegl1-mesa-dev libdbus-1-dev libibus-1.0-dev libudev-dev
7377
- name: Cache CMake dependency build objects
7478
uses: actions/cache@v4
7579
env:

CircuitLib/DFF.cir

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
version_7
1+
version_8
22
Circuit: "DFF"
33
UUID: d76f150e-28ee-48a3-8703-92b89613a0ed
44
size: 2x2
55
ports:
6-
(OUT, 3, 13, <1, 1>, "Q'")
7-
(OUT, 2, 7, <1, 0>, "Q")
8-
(IN, 1, 3, <0, 1>, "CLK")
9-
(IN, 0, 5, <0, 0>, "D")
6+
(IN, 0, (0, 0), <0, 0>, <0.100000, 0.500000>, "D", 1)
7+
(IN, 1, (0, 1), <0, 1>, <0.100000, 0.500000>, "CLK", 1)
8+
(OUT, 2, (6, 0), <1, 0>, <0.900000, 0.500000>, "Q", 1)
9+
(OUT, 3, (6, 1), <1, 1>, <0.900000, 0.500000>, "Q'", 1)
1010
blockId 13 LIGHT 6 1 ZERO
1111
(connId:0) (8 1)
1212
blockId 12 NOR 1 1 ZERO
@@ -17,28 +17,28 @@ blockId 11 NOR 4 1 ZERO
1717
(connId:1) (8 0)
1818
blockId 10 NOR 5 0 ZERO
1919
(connId:0) (8 1) (9 1)
20-
(connId:1) (8 0) (7 0)
20+
(connId:1) (7 0) (8 0)
2121
blockId 9 NOR 4 0 ZERO
2222
(connId:0) (3 0) (6 1)
2323
(connId:1) (10 0)
2424
blockId 8 NOR 5 1 ZERO
25-
(connId:1) (10 0) (13 0)
2625
(connId:0) (10 1) (11 1)
26+
(connId:1) (10 0) (13 0)
2727
blockId 7 LIGHT 6 0 ZERO
2828
(connId:0) (10 1)
2929
blockId 6 NAND 3 0 ZERO
3030
(connId:0) (1 1) (4 1)
3131
(connId:1) (4 0) (9 0)
3232
blockId 5 SWITCH 0 0 ZERO
33-
(connId:0) (12 0) (1 0)
33+
(connId:0) (1 0) (12 0)
3434
blockId 4 NAND 3 1 ZERO
35-
(connId:1) (6 0) (11 0)
3635
(connId:0) (2 1) (6 1)
36+
(connId:1) (6 0) (11 0)
3737
blockId 3 SWITCH 0 1 ZERO
38-
(connId:0) (2 0) (9 0) (1 0) (11 0)
38+
(connId:0) (1 0) (2 0) (9 0) (11 0)
3939
blockId 2 NAND 2 1 ZERO
40-
(connId:1) (4 0)
4140
(connId:0) (3 0) (12 1)
41+
(connId:1) (4 0)
4242
blockId 1 NAND 2 0 ZERO
43-
(connId:1) (6 0)
4443
(connId:0) (3 0) (5 0)
44+
(connId:1) (6 0)

CircuitLib/procedural/buildWasm.py

Lines changed: 129 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,134 @@
1-
import os
21
import pathlib
2+
import json
3+
import hashlib
4+
import os
5+
6+
import colorama
7+
colorama.init()
8+
9+
def build(source: pathlib.Path, target: pathlib.Path):
10+
assert (source.suffix in [".zig", ".rs", ".c", ".cpp", ".cc"])
11+
assert (target.suffix == ".wasm")
12+
os.chdir(source.parent)
13+
res = 0
14+
if source.suffix == ".zig":
15+
res = os.system(f"zig build-exe {source} -target wasm32-freestanding -fno-entry -rdynamic -O ReleaseSmall -femit-bin={target}")
16+
elif source.suffix == ".rs":
17+
return False # Rust builds are currently disabled
18+
res = os.system(f"rustc {source} -target wasm32-unknown-unknown -O -o {target}")
19+
elif source.suffix in [".cc", ".c", ".cpp"]:
20+
res = os.system(f"emcc {source} -Os -flto -s STANDALONE_WASM -s EXPORTED_FUNCTIONS=\"['_generateCircuit', '_getUUID', '_getName', '_getDefaultParameters']\" --no-entry -o {target}")
21+
return res == 0
22+
23+
BuildCache = dict[str, str]
24+
25+
def load_build_cache(path: pathlib.Path) -> BuildCache:
26+
if not path.exists():
27+
return {}
28+
with open(path, "r") as f:
29+
return json.load(f)
30+
31+
def get_relative_path(file_path: pathlib.Path, parent: pathlib.Path) -> str:
32+
try:
33+
return file_path.resolve().relative_to(parent).as_posix()
34+
except ValueError:
35+
return file_path.resolve().as_posix()
36+
37+
def normalize_cache(build_cache: BuildCache, script_dir: pathlib.Path) -> tuple[BuildCache, bool]:
38+
normalized_cache: BuildCache = {}
39+
cache_normalized = False
40+
for path_str, hash_val in build_cache.items():
41+
normalized_key = get_relative_path(pathlib.Path(path_str), script_dir)
42+
if normalized_key != path_str:
43+
cache_normalized = True
44+
normalized_cache[normalized_key] = hash_val
45+
return normalized_cache, cache_normalized
46+
47+
def get_all_source_files_from_folder(folder_path: pathlib.Path) -> list[pathlib.Path]:
48+
for file_group in folder_path.walk():
49+
for filename in file_group[2]:
50+
file = file_group[0] / pathlib.Path(filename)
51+
yield file
52+
53+
def get_all_filtered_source_files_from_folder(folder_path: pathlib.Path) -> list[pathlib.Path]:
54+
for file in get_all_source_files_from_folder(folder_path):
55+
if file.suffix not in [".zig", ".rs", ".c", ".cpp", ".cc"]:
56+
continue
57+
if file.stem == "cm":
58+
continue
59+
yield file
60+
61+
def get_all_source_files(folder_paths: list[pathlib.Path], script_dir: pathlib.Path) -> list[pathlib.Path]:
62+
file_paths: list[pathlib.Path] = []
63+
for folder_path in folder_paths:
64+
for file in get_all_filtered_source_files_from_folder(folder_path):
65+
file_paths.append(file)
66+
return file_paths
67+
68+
def calculate_file_hash(file_path: pathlib.Path) -> str:
69+
hasher = hashlib.new("md5")
70+
with file_path.open("r", encoding="utf-8", newline=None) as f:
71+
while True:
72+
data = f.read(8192)
73+
if not data:
74+
break
75+
hasher.update(data.encode("utf-8"))
76+
return hasher.hexdigest()
77+
78+
def build_file_considering_cache(file: pathlib.Path, build_cache: BuildCache, target_directory: pathlib.Path, script_dir: pathlib.Path):
79+
file_hash = calculate_file_hash(file)
80+
file_relative = get_relative_path(file, script_dir)
81+
target_file = target_directory / pathlib.Path(file.stem + '.wasm')
82+
target_file_relative = get_relative_path(target_file, script_dir)
83+
if file_relative in build_cache:
84+
entry = build_cache[file_relative]
85+
if entry == file_hash and pathlib.Path(script_dir / target_file_relative).exists():
86+
return False, False
87+
print(colorama.Fore.GREEN + "Building" + colorama.Style.RESET_ALL, file)
88+
success = build(file, target_file)
89+
if not success:
90+
print(colorama.Fore.RED + "Build failed for" + colorama.Style.RESET_ALL, file)
91+
return False, True
92+
build_cache[file_relative] = file_hash
93+
return True, False
94+
95+
def build_files(file_paths: list[pathlib.Path], build_cache: BuildCache, target_directory: pathlib.Path, script_dir: pathlib.Path) -> bool:
96+
build_cache_updated = False
97+
error_occured = False
98+
for file in file_paths:
99+
built, error = build_file_considering_cache(file, build_cache, target_directory, script_dir)
100+
if error:
101+
error_occured = True
102+
if built:
103+
build_cache_updated = True
104+
return build_cache_updated, error_occured
105+
106+
def main():
107+
script_dir = pathlib.Path(__file__).parent.resolve()
108+
109+
build_cache_path = script_dir/"build_cache.json"
110+
build_cache: BuildCache = load_build_cache(build_cache_path)
111+
112+
normalized_cache, cache_normalized = normalize_cache(build_cache, script_dir)
113+
build_cache = normalized_cache
114+
115+
folders = [
116+
"cpp",
117+
"zig",
118+
# "rust",
119+
]
3120

4-
file_path = (pathlib.Path(__file__).parent/"wasm").resolve()
5-
os.chdir(file_path)
121+
folder_paths = [(script_dir/folder).resolve() for folder in folders]
122+
target_directory = (script_dir/"wasm").resolve()
6123

7-
file = ".." / pathlib.Path("cpp/box.cpp")
8-
# file = ".." / pathlib.Path("zig/edge_detector.zig")
9-
# file = ".." / pathlib.Path("rust/edge_detector.rs")
124+
file_paths = get_all_source_files(folder_paths, script_dir)
125+
build_cache_updated, error_occured = build_files(file_paths, build_cache, target_directory, script_dir)
126+
if build_cache_updated or cache_normalized:
127+
with open(build_cache_path, "w") as f:
128+
json.dump(build_cache, f, indent=4)
10129

11-
if file.suffix == ".zig":
12-
os.system(f"zig build-exe {file} -target wasm32-freestanding -fno-entry -rdynamic -O ReleaseSmall")
13-
elif file.suffix == ".rs":
14-
os.system(f"rustc {file} -target wasm32-unknown-unknown -O -o {file.stem}.wasm")
15-
elif file.suffix in [".cc", ".c", ".cpp"]:
16-
os.system(f"emcc {file} -Os -flto -s STANDALONE_WASM -s EXPORTED_FUNCTIONS=\"['_generateCircuit', '_getUUID', '_getName', '_getDefaultParameters']\" --no-entry -o {file.stem}.wasm")
17-
else:
18-
raise Exception("File must be .zig, .rx, .c, .cpp, or .cc")
130+
if not build_cache_updated and not error_occured:
131+
print(colorama.Fore.GREEN + "All files are up to date :)" + colorama.Style.RESET_ALL)
19132

20-
# os.system("wasm-objdump -x " + str(file_path / pathlib.Path(file.name[:file.name.rfind(".")])) + ".wasm")
133+
if __name__ == "__main__":
134+
main()
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"cpp/adder.cpp": "46914ebe5d3e5f3d5e02d48e328cd603",
3+
"cpp/andGate.cpp": "a66f51229f93f4f2c943586a6b82cd9c",
4+
"cpp/box.cpp": "c4a9b81b2f3d2c04ff36a08ec170a407",
5+
"cpp/edgeDetector.cpp": "35ecaa6df21b65c1a77bb82503785bf4",
6+
"zig/edge_detector.zig": "4bbb46d6c2d6a975381368a69ca9eef9",
7+
"zig/bus_test.zig": "be7d3fb06977926039ace644ed7d41ed"
8+
}

CircuitLib/procedural/cpp/cm.h

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ extern "C"
2121
typedef unsigned int connection_end_id_t;
2222
typedef unsigned char block_size_t;
2323
typedef int block_id_t;
24-
typedef int cord_t;
24+
typedef int coord_t;
2525

2626
typedef char Rotation;
2727

@@ -32,12 +32,14 @@ extern "C"
3232
externalFunction(getPrimitiveType) BlockType getPrimitiveType(const char* primitiveName);
3333
externalFunction(getNonPrimitiveType) BlockType getNonPrimitiveType(const char* UUID);
3434
externalFunction(getProceduralCircuitType) BlockType getProceduralCircuitType(const char* UUID, const char* parameters);
35+
externalFunction(getBusBlock) BlockType getBusBlock(unsigned int bitWidth);
36+
externalFunction(getBusBlockAdvanced) BlockType getBusBlockAdvanced(unsigned int numInputs, unsigned int numOutputs, unsigned int inputLaneWidth, unsigned int outputLaneWidth);
3537
externalFunction(createBlock) block_id_t createBlock(BlockType blockType);
36-
externalFunction(createBlockAtPosition) block_id_t createBlockAtPosition(cord_t x, cord_t y, Rotation rotation, BlockType blockType);
38+
externalFunction(createBlockAtPosition) block_id_t createBlockAtPosition(coord_t x, coord_t y, Rotation rotation, BlockType blockType);
3739
externalFunction(createConnection) void createConnection(block_id_t outputBlockId, int outputPortId, block_id_t inputBlockId, int inputPortId);
38-
externalFunction(addConnectionInput) void addConnectionInput(cord_t portX, cord_t portY, block_id_t internalBlockId, connection_end_id_t internalBlockPortId);
39-
externalFunction(addConnectionOutput) void addConnectionOutput(cord_t portX, cord_t portY, block_id_t internalBlockId, connection_end_id_t internalBlockPortId);
40-
externalFunction(setSize) void setSize(cord_t width, cord_t height);
40+
externalFunction(addConnectionInput) void addConnectionInput(coord_t portX, coord_t portY, block_id_t internalBlockId, connection_end_id_t internalBlockPortId);
41+
externalFunction(addConnectionOutput) void addConnectionOutput(coord_t portX, coord_t portY, block_id_t internalBlockId, connection_end_id_t internalBlockPortId);
42+
externalFunction(setSize) void setSize(coord_t width, coord_t height);
4143
externalFunction(logInfo) void logInfo(const char* msg);
4244
externalFunction(logError) void logError(const char* msg);
4345
#ifdef __cplusplus

CircuitLib/procedural/rust/cm.rs

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ pub type BlockType = u32;
55
pub type connection_end_id_t = u32;
66
pub type block_size_t = u8;
77
pub type block_id_t = i32;
8-
pub type cord_t = i32;
8+
pub type coord_t = i32;
99
pub type Rotation = i8;
1010

1111
extern "C" {
@@ -17,10 +17,17 @@ extern "C" {
1717
pub fn getPrimitiveType(name: *const u8) -> BlockType;
1818
pub fn getNonPrimitiveType(uuid: *const u8) -> BlockType;
1919
pub fn getProceduralCircuitType(uuid: *const u8, params: *const u8) -> BlockType;
20+
pub fn getBusBlock(bit_width: i32) -> BlockType;
21+
pub fn getBusBlockAdvanced(
22+
num_inputs: i32,
23+
num_outputs: i32,
24+
input_lane_width: i32,
25+
output_lane_width: i32
26+
) -> BlockType;
2027

2128
// Block creation
2229
pub fn createBlock(block_type: BlockType) -> block_id_t;
23-
pub fn createBlockAtPosition(x: cord_t, y: cord_t, rotation: Rotation, block_type: BlockType) -> block_id_t;
30+
pub fn createBlockAtPosition(x: coord_t, y: coord_t, rotation: Rotation, block_type: BlockType) -> block_id_t;
2431

2532
// Connection functions
2633
pub fn createConnection(
@@ -31,21 +38,21 @@ extern "C" {
3138
);
3239

3340
pub fn addConnectionInput(
34-
external_port_x: cord_t,
35-
external_port_y: cord_t,
41+
external_port_x: coord_t,
42+
external_port_y: coord_t,
3643
internal_block_id: block_id_t,
3744
internal_port_id: connection_end_id_t,
3845
);
3946

4047
pub fn addConnectionOutput(
41-
external_port_x: cord_t,
42-
external_port_y: cord_t,
48+
external_port_x: coord_t,
49+
external_port_y: coord_t,
4350
internal_block_id: block_id_t,
4451
internal_port_id: connection_end_id_t,
4552
);
4653

4754
// Misc
48-
pub fn setSize(width: cord_t, height: cord_t);
55+
pub fn setSize(width: coord_t, height: coord_t);
4956
pub fn logInfo(msg: *const u8);
5057
pub fn logError(msg: *const u8);
5158
}
30 Bytes
Binary file not shown.
94 Bytes
Binary file not shown.
0 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)