From 737ae39d9cc4d80c307537bbbd8aefe253c80292 Mon Sep 17 00:00:00 2001 From: Cassie Jones Date: Sat, 27 Apr 2019 18:09:15 -0400 Subject: [PATCH] Generate the libery with a script --- .gitignore | 1 + example/counter.ys | 2 +- genlib.py | 100 +++++++++++++++++++++++++++++++++++++++++++++ makefile | 5 +++ minecraft.lib | 80 ------------------------------------ 5 files changed, 107 insertions(+), 81 deletions(-) create mode 100644 genlib.py create mode 100644 makefile delete mode 100644 minecraft.lib diff --git a/.gitignore b/.gitignore index 00806d2..cc2f533 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ /mc-mask/target +minecraft.lib diff --git a/example/counter.ys b/example/counter.ys index 9b899d3..4700bfd 100644 --- a/example/counter.ys +++ b/example/counter.ys @@ -1,5 +1,5 @@ read_verilog -sv example/counter.sv -read_liberty minecraft.lib +read_liberty -lib minecraft.lib synth dff2dffe abc -liberty minecraft.lib diff --git a/genlib.py b/genlib.py new file mode 100644 index 0000000..6531516 --- /dev/null +++ b/genlib.py @@ -0,0 +1,100 @@ +""" +Generate a cell library for redstone circuits +""" + +import sys + +CELLS = [ + (6, {'Y': 'A'}), + (6, {'Y': '!A'}), + (12, {'Y': 'A & B'}), + (12, {'Y': '!(A & B)'}), + (12, {'Y': 'A | B'}), + (12, {'Y': '!(A | B)'}), + (18, {'Y': 'A & B & C'}), + (18, {'Y': '!(A & B & C)'}), + (18, {'Y': 'A | B | C'}), + (18, {'Y': '!(A | B | C)'}), + (18, {'Y': '(A & B) | C'}), + (18, {'Y': '(A & B) | !C'}), + (18, {'Y': '!(A & B) | C'}), + (18, {'Y': '!(A & B) | !C'}), + (18, {'Y': '(A | B) & C'}), + (18, {'Y': '!((A | B) & C)'}), + (24, {'Y': 'A & B & C & D'}), + (24, {'Y': '!(A & B & C & D)'}), + (24, {'Y': 'A | B | C | D'}), + (24, {'Y': '!(A | B | C | D)'}), + (24, {'Y': '(A | B) & (C | D)'}), + (24, {'Y': '!((A | B) & (C | D))'}), + (24, {'Y': '(A & B) | (C & D)'}), + (24, {'Y': '(A & B) | !(C & D)'}), + (24, {'Y': '!(A & B) | !(C & D)'}), + (24, {'Y': '!((A & B) | !(C & D))'}), + (24, {'Y': '!(!(A & B) | (C & D))'}), + (24, {'Y': '!(!(A & B) | !(C & D))'}), + (24, {'Y': '(A | B) & C & D'}), + (24, {'Y': '!((A | B) & C & D)'}), + (24, {'Y': '(A | B) & (C | D)'}), + (24, {'Y': '!((A | B) & (C | D))'}), + """ +cell(DFF_P) { + area: 8; + ff(IQ, IQN) { clocked_on: C; next_state: D; } + pin(C) { direction: input; clock: true; } + pin(D) { direction: input; } + pin(Q) { direction: output; function: "IQ"; } +} + """, + """ +cell(DFF_N) { + area: 8; + ff(IQ, IQN) { clocked_on: "!C"; next_state: D; } + pin(C) { direction: input; clock: true; } + pin(D) { direction: input; } + pin(Q) { direction: output; function: "IQ"; } +} + """, +] + +def find_inputs(eqs): + inputs = set() + for eq in eqs.values(): + inputs.update( + eq.replace('(', ' ').replace(')', ' ') + .replace('&', ' ').replace('|', ' ') + .replace('+', ' ').replace('*', ' ') + .replace('!', ' ').split() + ) + return inputs + +def make_name(eqs): + return ','.join( + f"{x}={f.replace(' ', '').replace('|', '+')}" + for x, f in eqs.items() + ) + +def print_lib(lib, defns): + print(f"library({lib}) {{") + defined = {} + for i, defn in enumerate(defns): + if isinstance(defn, str): + print(' ' + defn.strip().replace('\n', '\n ')) + else: + area, eqs = defn + name = make_name(eqs) + if name in defined: + print(f"Warning: {name} defined at both {defined[name]} and {i}, skipping...", file=sys.stderr) + continue + defined[name] = i + inputs = find_inputs(eqs) + print(f""" cell("{name}") {{""") + print(f""" area: {area};""") + for pin in sorted(inputs): + print(f" pin({pin}) {{ direction: input; }}") + for x, f in eqs.items(): + print(f""" pin({x}) {{ direction: output; function: "{f}"; }}""") + print(" }") + print("}") + +print_lib("redstone", CELLS) diff --git a/makefile b/makefile new file mode 100644 index 0000000..cc3b15a --- /dev/null +++ b/makefile @@ -0,0 +1,5 @@ +synth: example/counter.ys minecraft.lib example/counter.sv + yosys $< + +minecraft.lib: genlib.py + python3 $< > $@ diff --git a/minecraft.lib b/minecraft.lib deleted file mode 100644 index 5875b29..0000000 --- a/minecraft.lib +++ /dev/null @@ -1,80 +0,0 @@ -// A cell library for redstone circuits -library(redstone) { - cell(REPEATER) { - area: 3; - pin(A) { direction: input; } - pin(Y) { direction: output; function: "A"; } - } - // @TODO: Nail down how we count area. - cell(NOT) { - area: 4; - pin(A) { direction: input; } - pin(Y) { direction: output; function: "!A"; } - } - cell(AND) { - area: 10; - pin(A) { direction: input; } - pin(B) { direction: input; } - pin(Y) { direction: output; function: "A & B"; } - } - cell(NAND) { - area: 9; - pin(A,B) { direction: input; } - pin(Y) { direction: output; function: "!(A & B)"; } - } - cell(OR) { - area: 3; - pin(A) { direction: input; } - pin(B) { direction: input; } - pin(Y) { direction: output; function: "A | B"; } - } - cell(NOR) { - area: 4; - pin(A) { direction: input; } - pin(B) { direction: input; } - pin(Y) { direction: output; function: "!(A | B)"; } - } - cell(AND3) { - area: 16; - pin(A) { direction: input; } - pin(B) { direction: input; } - pin(C) { direction: input; } - pin(Y) { direction: output; function: "A & B & C"; } - } - cell(NAND3) { - area: 15; - pin(A) { direction: input; } - pin(B) { direction: input; } - pin(C) { direction: input; } - pin(Y) { direction: output; function: "!(A & B & C)"; } - } - cell(OR3) { - area: 4; - pin(A) { direction: input; } - pin(B) { direction: input; } - pin(C) { direction: input; } - pin(Y) { direction: output; function: "A | B | C"; } - } - cell(NOR3) { - area: 5; - pin(A) { direction: input; } - pin(B) { direction: input; } - pin(C) { direction: input; } - pin(Y) { direction: output; function: "!(A | B | C)"; } - } - cell(DFF_P) { - area: 8; - ff(IQ, IQN) { clocked_on: C; next_state: D; } - pin(C) { direction: input; clock: true; } - pin(D) { direction: input; } - pin(Q) { direction: output; function: "IQ"; } - } - cell(DFF_N) { - area: 8; - ff(IQ, IQN) { clocked_on: "!C"; next_state: D; } - pin(C) { direction: input; clock: true; } - pin(D) { direction: input; } - pin(Q) { direction: output; function: "IQ"; } - } - // @TODO: Is there a good DFFE design? -} -- 2.43.2