diff options
-rwxr-xr-x | render.py | 1 | ||||
-rw-r--r-- | sem6/dig/common.mk | 29 | ||||
-rwxr-xr-x | sem6/dig/generate_test_file.py | 118 | ||||
-rw-r--r-- | sem6/dig/m2/Makefile | 30 | ||||
-rw-r--r-- | sem6/dig/m2/ex2.vhdl | 17 | ||||
-rw-r--r-- | sem6/dig/m2/ex5.vhdl | 18 | ||||
-rw-r--r-- | sem6/dig/m2/ex6.vhdl | 59 | ||||
-rwxr-xr-x | sem6/dig/m2/generate_test_file.py | 76 | ||||
-rw-r--r-- | sem6/dig/template.mk | 4 |
9 files changed, 248 insertions, 104 deletions
@@ -10,6 +10,7 @@ import re tex_template = """\\documentclass[12pt]{article} \\usepackage{amsmath} \\usepackage{amsfonts} +\\usepackage{mdframed} \\newtheorem{definition}{Definition} \\newtheorem{lemma}{Lemma} diff --git a/sem6/dig/common.mk b/sem6/dig/common.mk new file mode 100644 index 0000000..266511b --- /dev/null +++ b/sem6/dig/common.mk @@ -0,0 +1,29 @@ + + +all: $(INPUTFILES) + +.PHONY: all clean + +%.o: %.vhdl + ghdl -a $^ + +$(INPUTFILES): %: %.o + ghdl -e $@ + +test_%.vhdl: %.vhdl ../generate_test_file.py + ../generate_test_file.py $< $@ + +test_%: test_%.o + ghdl -e $@ + +run_%: % + ghdl -r $^ + +sim_%: test_% % + -./$< --vcd=out.vcd + +clean: + ghdl --clean + rm -f work*.cf + rm -f test_*.vhdl + diff --git a/sem6/dig/generate_test_file.py b/sem6/dig/generate_test_file.py new file mode 100755 index 0000000..42b8c8f --- /dev/null +++ b/sem6/dig/generate_test_file.py @@ -0,0 +1,118 @@ +#!/usr/bin/env python +# WOW THIS IS TERRIBLE +import json +import argparse +import re +import sys +import os +import jinja2 as j2 + +test_define_re = re.compile("TEST_START(.*)TEST_STOP") + +parser = argparse.ArgumentParser() +parser.add_argument("file", help="vhdl file to read from") +parser.add_argument("output", help="vhdl file to save to") + +args = parser.parse_args() + +def load_file_def(fname): + filecontent = "" + with open(fname, "r") as f: + filecontent = f.read() + + groups = test_define_re.search(filecontent).groups() + if groups: + return json.loads(groups[0]) + else: + print("No def in file", f=sys.stderr) + +test_def = load_file_def(args.file) +name = os.path.splitext(args.file)[0] + +def generate_vhdl_file(f, td, name): + def tof(s): + f.write(s) + + tof(f""" +library IEEE; +use IEEE.STD_LOGIC_1164.all; + +entity test_{name} is +end test_{name}; + +architecture behavior of test_{name} is + component {name} is + port ( + """) + + # Generate PORT section + first = True + for i in td["inputs"]: + if not first: + tof(";\n") + first = False + args = i.split(",") + if len(args) > 1: + tof(f"{args[0]} : IN STD_LOGIC_VECTOR({args[1]} downto {args[2]})") + else: + # Not a vector + tof(f"{args[0]} : IN STD_LOGIC") + for o in td["outputs"]: + if not first: + tof(";\n") + first = False + args = o.split(",") + if len(args) > 1: + tof(f"{args[0]} : OUT STD_LOGIC_VECTOR({args[1]} downto {args[2]})") + else: + # Not a vector + tof(f"{args[0]} : OUT STD_LOGIC") + tof(");\nend component;\n"); + + # Define signals + for i in td["inputs"]: + args = i.split(",") + if len(args) > 1: + tof(f"signal in_{args[0]} : STD_LOGIC_VECTOR({args[1]} downto {args[2]});\n") + else: + # Not a vector + tof(f"signal in_{args[0]} : STD_LOGIC;\n") + for i in td["outputs"]: + args = i.split(",") + if len(args) > 1: + tof(f"signal out_{args[0]} : STD_LOGIC_VECTOR({args[1]} downto {args[2]});\n") + else: + # Not a vector + tof(f"signal out_{args[0]} : STD_LOGIC;\n") + tof(f"""\nbegin + uut: {name} port map(\n""") + + first = True + for i in td["inputs"]: + if not first: + tof(",\n") + first = False + args = i.split(",") + tof(f"{args[0]} => in_{args[0]}") + for i in td["outputs"]: + if not first: + tof(",\n") + first = False + args = i.split(",") + tof(f"{args[0]} => out_{args[0]}") + tof(");\n\nstim_proc: process\nbegin\n") + + for t in td["testin"]: + for index, i in enumerate(td["inputs"]): + args = i.split(",") + if len(args) > 1: + tof(f"in_{args[0]} <= \"{t[index]}\";") + else: + tof(f"in_{args[0]} <= '{t[index]}';") + tof("wait for 1 fs;") + tof("wait;\nend process;\nend;") + + +with open(args.output, "w") as f: + generate_vhdl_file(f, test_def, name) + diff --git a/sem6/dig/m2/Makefile b/sem6/dig/m2/Makefile index 2731d67..4f83294 100644 --- a/sem6/dig/m2/Makefile +++ b/sem6/dig/m2/Makefile @@ -1,30 +1,4 @@ -INPUTFILES=nor_gate - -all: $(INPUTFILES) - -.PHONY: all clean - -%.o: %.vhdl - ghdl -a $^ - -$(INPUTFILES): %: %.o - ghdl -e $@ - -test_%.vhdl: %.vhdl generate_test_file.py - ./generate_test_file.py $< $@ - -test_$(INPUTFILES): %: %.o - ghdl -e $@ - -run_%: % - ghdl -r $^ - -sim_%: test_% % - -./$< --vcd=out.vcd - -clean: - ghdl --clean - rm -f work*.cf - rm -f test_*.vhdl +INPUTFILES = nor_gate ex2 ex5 ex6 +include ../common.mk diff --git a/sem6/dig/m2/ex2.vhdl b/sem6/dig/m2/ex2.vhdl new file mode 100644 index 0000000..7fb7168 --- /dev/null +++ b/sem6/dig/m2/ex2.vhdl @@ -0,0 +1,17 @@ +-- TEST_START{"inputs": ["sw1", "sw2", "sw3", "sw4"], "outputs": ["LED"], "testin": ["0000", "0001", "0101", "1101"]}TEST_STOP +LIBRARY IEEE; +USE IEEE.STD_LOGIC_1164.all; + +ENTITY ex2 IS + PORT( + sw1: IN STD_LOGIC; + sw2: IN STD_LOGIC; + sw3: IN STD_LOGIC; + sw4: IN STD_LOGIC; + led: OUT STD_LOGIC); +END ex2; + +ARCHITECTURE impl OF ex2 IS +BEGIN + led <= (sw1 AND sw2) OR NOT(sw3 AND sw4); +END impl; diff --git a/sem6/dig/m2/ex5.vhdl b/sem6/dig/m2/ex5.vhdl new file mode 100644 index 0000000..bfc27b9 --- /dev/null +++ b/sem6/dig/m2/ex5.vhdl @@ -0,0 +1,18 @@ +-- TEST_START{"inputs": ["a", "b", "cin"], "outputs": ["o", "cout"], "testin": ["000", "010", "100", "110", "011", "111"]}TEST_STOP +LIBRARY IEEE; +USE IEEE.STD_LOGIC_1164.all; + +ENTITY ex5 IS + PORT( + a: IN STD_LOGIC; + b: IN STD_LOGIC; + cin: IN STD_LOGIC; + o: OUT STD_LOGIC; + cout: OUT STD_LOGIC); +END ex5; + +ARCHITECTURE impl OF ex5 IS +BEGIN + o <= (a XOR b) XOR cin; + cout <= (a AND b) OR (cin AND (a OR b)); +END impl; diff --git a/sem6/dig/m2/ex6.vhdl b/sem6/dig/m2/ex6.vhdl new file mode 100644 index 0000000..e920c98 --- /dev/null +++ b/sem6/dig/m2/ex6.vhdl @@ -0,0 +1,59 @@ +-- TEST_START{"inputs": ["cin", "a,3,0", "b,3,0"], "outputs": ["carry", "output,3,0"], "testin": [["0", "0001", "0001"], ["0", "0101", "1010"], ["0", "1111", "1111"], ["1", "0000", "0000"]]}TEST_STOP +LIBRARY IEEE; +USE IEEE.STD_LOGIC_1164.all; + +ENTITY ex6 IS + PORT( + a : IN STD_LOGIC_VECTOR(3 downto 0); + b : IN STD_LOGIC_VECTOR(3 downto 0); + cin: IN STD_LOGIC; + output: OUT STD_LOGIC_VECTOR(3 downto 0); + carry : OUT STD_LOGIC + ); +END ex6; + +ARCHITECTURE impl OF ex6 IS + SIGNAL c1 : STD_LOGIC; + SIGNAL c2 : STD_LOGIC; + SIGNAL c3 : STD_LOGIC; + SIGNAL c4 : STD_LOGIC; + +BEGIN + + add1 : ENTITY work.ex5 + PORT MAP ( + a => a(0), + b => b(0), + cin => cin, + o => output(0), + cout => c1 + ); + + add2 : ENTITY work.ex5 + PORT MAP ( + a => a(1), + b => b(1), + cin => c1, + o => output(1), + cout => c2 + ); + + add3 : ENTITY work.ex5 + PORT MAP ( + a => a(2), + b => b(2), + cin => c2, + o => output(2), + cout => c3 + ); + + add4 : ENTITY work.ex5 + PORT MAP ( + a => a(3), + b => b(3), + cin => c3, + o => output(3), + cout => carry + ); +END impl; + diff --git a/sem6/dig/m2/generate_test_file.py b/sem6/dig/m2/generate_test_file.py deleted file mode 100755 index c450f02..0000000 --- a/sem6/dig/m2/generate_test_file.py +++ /dev/null @@ -1,76 +0,0 @@ -#!/usr/bin/env python -import json -import argparse -import re -import sys -import os -import jinja2 as j2 - -test_define_re = re.compile("TEST_START(.*)TEST_STOP") - -parser = argparse.ArgumentParser() -parser.add_argument("file", help="vhdl file to read from") -parser.add_argument("output", help="vhdl file to save to") - -args = parser.parse_args() - -def load_file_def(fname): - filecontent = "" - with open(fname, "r") as f: - filecontent = f.read() - - groups = test_define_re.search(filecontent).groups() - if groups: - return json.loads(groups[0]) - else: - print("No def in file", f=sys.stderr) - -test_def = load_file_def(args.file) -name = os.path.splitext(args.file)[0] - -# Generate test file, by running all inputs TODO make this more configurable - -testbed_template = j2.Template(""" -library IEEE; -use IEEE.STD_LOGIC_1164.all; - -entity test_{{name}} is -end test_{{name}}; - -architecture behavior of test_{{name}} is - component {{name}} is - port ( - {% for input in inputs %}{{input}}: in std_logic; - {% endfor %}{% for output in outputs %}{{output}}: out std_logic{% if not loop.last %};{% endif %} - {% endfor %}); - end component; - signal input : std_logic_vector({{ num_inputs - 1 }} downto 0); - signal output : std_logic_vector({{ num_inputs - 1 }} downto 0); -begin - uut: {{name}} port map ( - {% for input in inputs %}{{input}} => input({{loop.index-1}}), - {% endfor %}{% for output in outputs %}{{output}} => output({{loop.index-1}}){% if not loop.last %},{% endif %}{% endfor %} - ); - - stim_proc: process - begin - {% for test in testin %} - input <= "{{test}}"; wait for 1 fs; - {% endfor %} - wait; - end process; -end; -""") - -render = testbed_template.render( - name=name, - inputs=test_def["inputs"], - num_inputs=len(test_def["inputs"]), - outputs=test_def["outputs"], - num_outputs=len(test_def["outputs"]), - testin=test_def["testin"] - ) - -with open(args.output, "w") as f: - print(render, file=f) - diff --git a/sem6/dig/template.mk b/sem6/dig/template.mk new file mode 100644 index 0000000..0232d3a --- /dev/null +++ b/sem6/dig/template.mk @@ -0,0 +1,4 @@ + +INPUTFILES=nor_gate + +include ../common.mk |