Compare commits

..

No commits in common. "d60b8c53717750a61ea816550456a72ce1f76602" and "ab5fda541cb83f4597081efcc9da027c10d1592d" have entirely different histories.

11 changed files with 151 additions and 201 deletions

View file

@ -1,5 +1,5 @@
workdir/ workdir/
*.o *.o
*.ghw *.ghw
day2 sim
top_syn.vhd top_syn.vhd

View file

@ -1,16 +0,0 @@
configuration day2 of sim is
for aoc_stdio
for dut_inst: dut
use entity work.top port map (
clk => clk,
reset => reset,
char => char,
input_valid => input_valid,
num_verified => output,
output_valid => output_valid
);
end for;
end for;
end configuration;

View file

@ -5,12 +5,10 @@ entity parser is
port ( port (
clk : in std_logic; clk : in std_logic;
reset : in std_logic; reset : in std_logic;
is_record : in std_logic;
is_data : out std_logic; is_data : out std_logic;
record_end : out std_logic;
char : in character; char : in character;
input_valid : in std_logic;
num1, num2 : out natural range 0 to 99; num1, num2 : out natural range 0 to 99;
letter : out character letter : out character
@ -45,22 +43,22 @@ begin
process(clk) process(clk)
begin begin
if rising_edge(clk) then if rising_edge(clk) then
record_end <= '0';
if reset then if reset then
prev_digit <= 0; prev_digit <= 0;
state <= S_NUM1; state <= S_NUM1;
elsif input_valid then else
prev_digit <= 0; prev_digit <= 0;
case state is case state is
when S_NUM1 => when S_NUM1 =>
if is_record then
if char = '-' then if char = '-' then
state <= S_NUM2; state <= S_NUM2;
else else
num1 <= complete_num; num1 <= complete_num;
prev_digit <= current_digit; prev_digit <= current_digit;
end if; end if;
end if;
when S_NUM2 => when S_NUM2 =>
if char = ' ' then if char = ' ' then
state <= S_LETTER; state <= S_LETTER;
@ -76,9 +74,8 @@ begin
when S_END_SPACE => when S_END_SPACE =>
state <= S_DATA; state <= S_DATA;
when S_DATA => when S_DATA =>
if char = LF then if not is_record then
state <= S_NUM1; state <= S_NUM1;
record_end <= '1';
end if; end if;
end case; end case;
end if; end if;

View file

@ -1,8 +1,25 @@
#!/bin/bash #!/usr/bin/bash
source "$COMMON_DIR/vhdl_run.sh" set -eu
INPUT=$(readlink --canonicalize-existing "$1")
MODE=${2:-}
GHDLFLAGS="--std=08 --workdir=workdir"
cd "$(dirname "${BASH_SOURCE[0]}")" cd "$(dirname "${BASH_SOURCE[0]}")"
DUT_OUTPUT_WIDTH=12 mkdir -p workdir
test_synth day2 parser.vhdl verifier.vhdl top.vhdl
if [[ $MODE = "--synth" ]]; then
for step in 1 2; do
ghdl remove $GHDLFLAGS
ghdl synth $GHDLFLAGS -gCOUNTER_WIDTH=12 -gSTEP="$step" parser.vhd verifier.vhd top.vhd -e top > top_syn.vhd 2>/dev/null
ghdl analyze $GHDLFLAGS top_syn.vhd sim.vhd
ghdl elab-run $GHDLFLAGS sim -gSTEP="$step" --ieee-asserts=disable < "$INPUT"
done
else
ghdl remove $GHDLFLAGS
ghdl analyze $GHDLFLAGS parser.vhd verifier.vhd top.vhd sim.vhd
ghdl elab-run $GHDLFLAGS sim -gSTEP=1 < "$INPUT"
ghdl elab-run $GHDLFLAGS sim -gSTEP=2 < "$INPUT"
fi

View file

@ -1,15 +1,15 @@
[*] [*]
[*] GTKWave Analyzer v3.3.109 (w)1999-2020 BSI [*] GTKWave Analyzer v3.3.104 (w)1999-2020 BSI
[*] Wed Dec 1 11:30:36 2021 [*] Wed Dec 2 10:02:23 2020
[*] [*]
[dumpfile] "/home/xiretza/dev/advent-of-code/2020/day2/vhdl/workdir/sim1.ghw" [dumpfile] "/home/xiretza/dev/aoc2020/day2/sim.ghw"
[dumpfile_mtime] "Wed Dec 1 11:29:37 2021" [dumpfile_mtime] "Wed Dec 2 10:01:08 2020"
[dumpfile_size] 408417 [dumpfile_size] 410436
[savefile] "/home/xiretza/dev/advent-of-code/2020/day2/vhdl/sim.gtkw" [savefile] "/home/xiretza/dev/aoc2020/day2/sim.gtkw"
[timestart] 411833500000 [timestart] 410945000000
[size] 1920 1035 [size] 1600 853
[pos] -1 -1 [pos] -1 -1
*-25.864407 520000000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 *-27.864407 226600000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
[treeopen] top. [treeopen] top.
[treeopen] top.sim. [treeopen] top.sim.
[treeopen] top.sim.top. [treeopen] top.sim.top.
@ -20,10 +20,9 @@
@28 @28
top.sim.clk top.sim.clk
top.sim.reset top.sim.reset
top.sim.top.parser_inst.is_record
@420 @420
top.sim.top.char top.sim.top.char
@28
top.sim.input_valid
@200 @200
- -
@28 @28
@ -34,13 +33,15 @@ top.sim.top.num2
top.sim.top.letter top.sim.top.letter
@200 @200
- -
@29 @420
top.sim.top.record_end top.sim.top.verifier_inst.count
@28 @28
top.sim.top.verified top.sim.top.verifier_inst.verified
@200 @200
- -
@24 @24
#{top.sim.num_verified[11:0]} top.sim.num_verified[11] top.sim.num_verified[10] top.sim.num_verified[9] top.sim.num_verified[8] top.sim.num_verified[7] top.sim.num_verified[6] top.sim.num_verified[5] top.sim.num_verified[4] top.sim.num_verified[3] top.sim.num_verified[2] top.sim.num_verified[1] top.sim.num_verified[0] #{top.sim.num_verified[11:0]} top.sim.num_verified[11] top.sim.num_verified[10] top.sim.num_verified[9] top.sim.num_verified[8] top.sim.num_verified[7] top.sim.num_verified[6] top.sim.num_verified[5] top.sim.num_verified[4] top.sim.num_verified[3] top.sim.num_verified[2] top.sim.num_verified[1] top.sim.num_verified[0]
@29
top.sim.top.record_ended
[pattern_trace] 1 [pattern_trace] 1
[pattern_trace] 0 [pattern_trace] 0

86
2020/day2/vhdl/sim.vhd Normal file
View file

@ -0,0 +1,86 @@
library ieee;
use ieee.std_logic_1164.all,
ieee.numeric_std.all;
use std.textio.all;
entity sim is
generic (
COUNTER_WIDTH : positive := 12;
STEP : natural range 1 to 2
);
end entity;
architecture a of sim is
signal char_in : character;
signal clk, reset, is_record : std_logic;
signal num_verified : unsigned(COUNTER_WIDTH-1 downto 0);
procedure print(s: string) is
variable l : line;
begin
write(l, s);
writeline(output, l);
end procedure;
begin
process
variable current_line : line;
variable current_char : character;
variable good : boolean;
procedure cycle_clock is
begin
wait for 10 ns;
clk <= '0';
wait for 10 ns;
clk <= '1';
wait for 0 ns;
end procedure;
begin
clk <= '0';
is_record <= '0';
char_in <= NUL;
reset <= '1';
cycle_clock;
reset <= '0';
cycle_clock;
lines_loop: loop
exit lines_loop when endfile(input);
readline(input, current_line);
is_record <= '1';
chars_loop: loop
read(current_line, current_char, good);
exit chars_loop when not good;
char_in <= current_char;
cycle_clock;
end loop;
is_record <= '0';
cycle_clock;
end loop;
cycle_clock;
print(to_string(to_integer(num_verified)));
wait;
end process;
top: entity work.top
generic map (
COUNTER_WIDTH => COUNTER_WIDTH,
STEP => STEP
)
port map (
clk => clk,
reset => reset,
char => char_in,
is_record => is_record,
num_verified => num_verified
);
end architecture;

View file

@ -4,18 +4,15 @@ use ieee.std_logic_1164.all,
entity top is entity top is
generic ( generic (
OUTPUT_WIDTH : positive; COUNTER_WIDTH : positive;
STEP : natural range 1 to 2 STEP : natural range 1 to 2
); );
port ( port (
clk : in std_logic; clk : in std_logic;
reset : in std_logic; reset : in std_logic;
char : in character; char : in character;
is_record : in std_logic;
input_valid : in std_logic; num_verified : out unsigned(COUNTER_WIDTH-1 downto 0)
num_verified : out unsigned(OUTPUT_WIDTH-1 downto 0) := (others => '0');
output_valid : out std_logic
); );
end entity; end entity;
@ -24,20 +21,20 @@ architecture behaviour of top is
signal num1, num2 : natural range 0 to 99; signal num1, num2 : natural range 0 to 99;
signal letter : character; signal letter : character;
signal record_end : std_logic; signal prev_is_record : std_logic;
signal record_ended : std_logic;
signal verified : std_logic; signal verified : std_logic;
begin begin
record_ended <= prev_is_record and not is_record;
parser_inst: entity work.parser parser_inst: entity work.parser
port map ( port map (
clk => clk, clk => clk,
reset => reset, reset => reset,
is_record => is_record,
record_end => record_end,
is_data => is_data, is_data => is_data,
char => char, char => char,
input_valid => input_valid,
num1 => num1, num1 => num1,
num2 => num2, num2 => num2,
@ -48,8 +45,8 @@ begin
verifier_inst: entity work.verifier(step1) verifier_inst: entity work.verifier(step1)
port map ( port map (
clk => clk, clk => clk,
reset => reset or record_end, reset => reset or record_ended,
enable => is_data and input_valid, is_data => is_data,
num1 => num1, num1 => num1,
num2 => num2, num2 => num2,
letter => letter, letter => letter,
@ -60,8 +57,8 @@ begin
verifier_inst: entity work.verifier(step2) verifier_inst: entity work.verifier(step2)
port map ( port map (
clk => clk, clk => clk,
reset => reset or record_end, reset => reset or record_ended,
enable => is_data and input_valid, is_data => is_data,
num1 => num1, num1 => num1,
num2 => num2, num2 => num2,
letter => letter, letter => letter,
@ -75,13 +72,13 @@ begin
process(clk) process(clk)
begin begin
if rising_edge(clk) then if rising_edge(clk) then
prev_is_record <= is_record;
if reset then if reset then
prev_is_record <= '0';
num_verified <= (others => '0'); num_verified <= (others => '0');
elsif record_end and verified then elsif record_ended and verified then
num_verified <= num_verified + 1; num_verified <= num_verified + 1;
end if; end if;
end if; end if;
end process; end process;
output_valid <= '1';
end architecture; end architecture;

View file

@ -5,7 +5,7 @@ entity verifier is
port ( port (
clk : in std_logic; clk : in std_logic;
reset : in std_logic; reset : in std_logic;
enable : in std_logic; is_data : in std_logic;
num1, num2 : in natural range 0 to 99; num1, num2 : in natural range 0 to 99;
letter : in character; letter : in character;
@ -24,7 +24,7 @@ begin
if rising_edge(clk) then if rising_edge(clk) then
if reset then if reset then
count <= 0; count <= 0;
elsif enable then elsif is_data then
if char = letter then if char = letter then
count <= count + 1; count <= count + 1;
end if; end if;
@ -45,7 +45,7 @@ begin
if reset then if reset then
count <= 1; count <= 1;
parity <= '0'; parity <= '0';
elsif enable then elsif is_data then
count <= count + 1; count <= count + 1;
if (count = num1 or count = num2) and char = letter then if (count = num1 or count = num2) and char = letter then
parity <= not parity; parity <= not parity;

View file

@ -1,100 +0,0 @@
library ieee;
use ieee.std_logic_1164.all,
ieee.numeric_std.all;
use std.textio.all;
entity sim is
generic (
OUTPUT_WIDTH : positive;
STEP : natural range 1 to 2
);
end entity;
architecture aoc_stdio of sim is
type char_file_t is file of character;
file stdin : char_file_t open READ_MODE is "STD_INPUT";
signal char_in : character;
signal clk, reset, input_valid, output_valid : std_logic;
signal output : unsigned(OUTPUT_WIDTH-1 downto 0);
procedure print(s: string) is
variable l : line;
begin
write(l, s);
writeline(std.textio.output, l);
end procedure;
component dut is
generic (
OUTPUT_WIDTH : positive;
STEP : natural range 1 to 2
);
port (
clk : in std_logic;
reset : in std_logic;
char : in character;
input_valid : in std_logic;
output : out unsigned(OUTPUT_WIDTH-1 downto 0);
output_valid : out std_logic
);
end component;
begin
process
variable current_char : character;
variable good : boolean;
procedure cycle_clock is
begin
wait for 10 ns;
clk <= '0';
wait for 10 ns;
clk <= '1';
wait for 0 ns;
end procedure;
begin
clk <= '0';
input_valid <= '0';
char_in <= NUL;
reset <= '1';
cycle_clock;
reset <= '0';
cycle_clock;
input_valid <= '1';
chars_loop: while not endfile(stdin) loop
read(stdin, current_char);
char_in <= current_char;
cycle_clock;
end loop;
input_valid <= '0';
cycle_clock;
cycle_clock;
assert output_valid report "Output was not valid at end of simulation" severity failure;
print(to_string(to_integer(output)));
wait;
end process;
dut_inst: dut
generic map (
OUTPUT_WIDTH => OUTPUT_WIDTH,
STEP => STEP
)
port map (
clk => clk,
reset => reset,
char => char_in,
input_valid => input_valid,
output => output,
output_valid => output_valid
);
end architecture;

View file

@ -1,30 +0,0 @@
#!/usr/bin/bash
set -euo pipefail
INPUT=$(readlink --canonicalize-existing "$1")
workdir=workdir
GHDLFLAGS="--std=08 --workdir=$workdir"
mkdir -p workdir
test_synth() {
local config_name=$1; shift
for step in 1 2; do
ghdl remove $GHDLFLAGS
ghdl synth $GHDLFLAGS -gOUTPUT_WIDTH="$DUT_OUTPUT_WIDTH" -gSTEP="$step" "$@" -e top > "$workdir/top_syn.vhdl" 2>/dev/null
ghdl analyze $GHDLFLAGS "$workdir/top_syn.vhdl" "$COMMON_DIR/testbench.vhdl" "$config_name.vhdl"
ghdl elab-run $GHDLFLAGS "$config_name" -gOUTPUT_WIDTH="$DUT_OUTPUT_WIDTH" --wave="$workdir/synth$step.ghw" --ieee-asserts=disable < "$INPUT"
done
}
test_sim() {
local config_name=$1; shift
ghdl remove $GHDLFLAGS
ghdl analyze $GHDLFLAGS "$COMMON_DIR/testbench.vhdl" "$@" "$config_name.vhdl"
for step in 1 2; do
ghdl elab-run $GHDLFLAGS "$config_name" -gOUTPUT_WIDTH="$DUT_OUTPUT_WIDTH" -gSTEP="$step" --wave="$workdir/sim$step.ghw" < "$INPUT"
done
}

View file

@ -6,8 +6,6 @@ cd "$(dirname "${BASH_SOURCE[0]}")"
YEAR=2020 YEAR=2020
export COMMON_DIR="$(realpath common)"
run_solution() { run_solution() {
if [ -d "$solution" ]; then if [ -d "$solution" ]; then
if [ -f "$solution/Cargo.toml" ]; then if [ -f "$solution/Cargo.toml" ]; then