vertigo_vhdl 0.8.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (183) hide show
  1. checksums.yaml +7 -0
  2. data/bin/vertigo +7 -0
  3. data/lib/vertigo.rb +4 -0
  4. data/lib/vertigo/ast.rb +87 -0
  5. data/lib/vertigo/ast_vertigo_rkgen.rb +607 -0
  6. data/lib/vertigo/code.rb +57 -0
  7. data/lib/vertigo/compiler.rb +61 -0
  8. data/lib/vertigo/generic_lexer.rb +61 -0
  9. data/lib/vertigo/generic_parser.rb +44 -0
  10. data/lib/vertigo/indent.rb +20 -0
  11. data/lib/vertigo/lexer.rb +172 -0
  12. data/lib/vertigo/parser.rb +1458 -0
  13. data/lib/vertigo/pretty_printer.rb +749 -0
  14. data/lib/vertigo/runner.rb +115 -0
  15. data/lib/vertigo/tb_generator.rb +81 -0
  16. data/lib/vertigo/template.tb.vhd +72 -0
  17. data/lib/vertigo/token.rb +67 -0
  18. data/lib/vertigo/version.rb +3 -0
  19. data/lib/vertigo/vertigo.rkg +354 -0
  20. data/lib/vertigo/visitor_vertigo_rkgen.rb +447 -0
  21. data/tests/ghdl_tests/fsm.vhd +98 -0
  22. data/tests/ghdl_tests/fsm_synth.vhd +248 -0
  23. data/tests/ghdl_tests/test_fsm.vhd +162 -0
  24. data/tests/parser_tests/else.vhd +64 -0
  25. data/tests/parser_tests/test_MUST_fail.vhd +1 -0
  26. data/tests/parser_tests/test_accelerator.vhd +160 -0
  27. data/tests/parser_tests/test_accelerator_pp.vhd +144 -0
  28. data/tests/parser_tests/test_aggregate.vhd +17 -0
  29. data/tests/parser_tests/test_aggregate_pp.vhd +15 -0
  30. data/tests/parser_tests/test_archi_1.vhd +45 -0
  31. data/tests/parser_tests/test_archi_1_pp.vhd +41 -0
  32. data/tests/parser_tests/test_array_array_00.vhd +25 -0
  33. data/tests/parser_tests/test_array_array_00_pp.vhd +25 -0
  34. data/tests/parser_tests/test_array_urange.vhd +25 -0
  35. data/tests/parser_tests/test_array_urange_pp.vhd +25 -0
  36. data/tests/parser_tests/test_chu-1.vhd +80 -0
  37. data/tests/parser_tests/test_chu-1_pp.vhd +104 -0
  38. data/tests/parser_tests/test_concat.vhd +11 -0
  39. data/tests/parser_tests/test_concat_pp.vhd +14 -0
  40. data/tests/parser_tests/test_counter.vhd +35 -0
  41. data/tests/parser_tests/test_counter_pp.vhd +35 -0
  42. data/tests/parser_tests/test_de2.vhd +358 -0
  43. data/tests/parser_tests/test_de2_pp.vhd +274 -0
  44. data/tests/parser_tests/test_encode.vhd +2679 -0
  45. data/tests/parser_tests/test_encode_pp.vhd +2549 -0
  46. data/tests/parser_tests/test_fsm.vhd +162 -0
  47. data/tests/parser_tests/test_fsm_pp.vhd +125 -0
  48. data/tests/parser_tests/test_fsm_synth.vhd +248 -0
  49. data/tests/parser_tests/test_fsm_synth_pp.vhd +197 -0
  50. data/tests/parser_tests/test_function-01.vhd +33 -0
  51. data/tests/parser_tests/test_function-01_pp.vhd +18 -0
  52. data/tests/parser_tests/test_lfsr.vhd +75 -0
  53. data/tests/parser_tests/test_lfsr_pp.vhd +44 -0
  54. data/tests/parser_tests/test_microwatt_cache_ram.vhd +1 -0
  55. data/tests/parser_tests/test_microwatt_cache_ram_pp.vhd +68 -0
  56. data/tests/parser_tests/test_microwatt_common.vhd +1 -0
  57. data/tests/parser_tests/test_microwatt_common_pp.vhd +336 -0
  58. data/tests/parser_tests/test_microwatt_control.vhd +1 -0
  59. data/tests/parser_tests/test_microwatt_control_pp.vhd +187 -0
  60. data/tests/parser_tests/test_microwatt_core.vhd +1 -0
  61. data/tests/parser_tests/test_microwatt_core_debug.vhd +1 -0
  62. data/tests/parser_tests/test_microwatt_core_debug_pp.vhd +104 -0
  63. data/tests/parser_tests/test_microwatt_core_pp.vhd +231 -0
  64. data/tests/parser_tests/test_microwatt_core_tb.vhd +1 -0
  65. data/tests/parser_tests/test_microwatt_core_tb_pp.vhd +43 -0
  66. data/tests/parser_tests/test_microwatt_countzero.vhd +1 -0
  67. data/tests/parser_tests/test_microwatt_countzero_pp.vhd +120 -0
  68. data/tests/parser_tests/test_microwatt_countzero_tb.vhd +1 -0
  69. data/tests/parser_tests/test_microwatt_countzero_tb_pp.vhd +70 -0
  70. data/tests/parser_tests/test_microwatt_cr_file.vhd +1 -0
  71. data/tests/parser_tests/test_microwatt_cr_file_pp.vhd +74 -0
  72. data/tests/parser_tests/test_microwatt_cr_hazard.vhd +1 -0
  73. data/tests/parser_tests/test_microwatt_cr_hazard_pp.vhd +51 -0
  74. data/tests/parser_tests/test_microwatt_crhelpers.vhd +1 -0
  75. data/tests/parser_tests/test_microwatt_crhelpers_pp.vhd +48 -0
  76. data/tests/parser_tests/test_microwatt_dcache.vhd +1 -0
  77. data/tests/parser_tests/test_microwatt_dcache_pp.vhd +481 -0
  78. data/tests/parser_tests/test_microwatt_dcache_tb.vhd +1 -0
  79. data/tests/parser_tests/test_microwatt_dcache_tb_pp.vhd +98 -0
  80. data/tests/parser_tests/test_microwatt_decode1.vhd +1 -0
  81. data/tests/parser_tests/test_microwatt_decode1_pp.vhd +138 -0
  82. data/tests/parser_tests/test_microwatt_decode2.vhd +1 -0
  83. data/tests/parser_tests/test_microwatt_decode2_pp.vhd +300 -0
  84. data/tests/parser_tests/test_microwatt_decode_types.vhd +1 -0
  85. data/tests/parser_tests/test_microwatt_decode_types_pp.vhd +67 -0
  86. data/tests/parser_tests/test_microwatt_divider.vhd +1 -0
  87. data/tests/parser_tests/test_microwatt_divider_pp.vhd +132 -0
  88. data/tests/parser_tests/test_microwatt_divider_tb.vhd +1 -0
  89. data/tests/parser_tests/test_microwatt_divider_tb_pp.vhd +95 -0
  90. data/tests/parser_tests/test_microwatt_dmi_dtm_dummy.vhd +1 -0
  91. data/tests/parser_tests/test_microwatt_dmi_dtm_dummy_pp.vhd +29 -0
  92. data/tests/parser_tests/test_microwatt_dmi_dtm_tb.vhd +1 -0
  93. data/tests/parser_tests/test_microwatt_dmi_dtm_tb_pp.vhd +197 -0
  94. data/tests/parser_tests/test_microwatt_dmi_dtm_xilinx.vhd +1 -0
  95. data/tests/parser_tests/test_microwatt_dmi_dtm_xilinx_pp.vhd +139 -0
  96. data/tests/parser_tests/test_microwatt_execute1.vhd +1 -0
  97. data/tests/parser_tests/test_microwatt_execute1_pp.vhd +689 -0
  98. data/tests/parser_tests/test_microwatt_fetch1.vhd +1 -0
  99. data/tests/parser_tests/test_microwatt_fetch1_pp.vhd +88 -0
  100. data/tests/parser_tests/test_microwatt_fetch2.vhd +1 -0
  101. data/tests/parser_tests/test_microwatt_fetch2_pp.vhd +79 -0
  102. data/tests/parser_tests/test_microwatt_glibc_random.vhd +1 -0
  103. data/tests/parser_tests/test_microwatt_glibc_random_helpers.vhd +1 -0
  104. data/tests/parser_tests/test_microwatt_glibc_random_helpers_pp.vhd +25 -0
  105. data/tests/parser_tests/test_microwatt_glibc_random_pp.vhd +41 -0
  106. data/tests/parser_tests/test_microwatt_gpr_hazard.vhd +1 -0
  107. data/tests/parser_tests/test_microwatt_gpr_hazard_pp.vhd +68 -0
  108. data/tests/parser_tests/test_microwatt_helpers.vhd +1 -0
  109. data/tests/parser_tests/test_microwatt_helpers_pp.vhd +153 -0
  110. data/tests/parser_tests/test_microwatt_icache.vhd +1 -0
  111. data/tests/parser_tests/test_microwatt_icache_pp.vhd +337 -0
  112. data/tests/parser_tests/test_microwatt_icache_tb.vhd +1 -0
  113. data/tests/parser_tests/test_microwatt_icache_tb_pp.vhd +104 -0
  114. data/tests/parser_tests/test_microwatt_insn_helpers.vhd +1 -0
  115. data/tests/parser_tests/test_microwatt_insn_helpers_pp.vhd +208 -0
  116. data/tests/parser_tests/test_microwatt_loadstore1.vhd +1 -0
  117. data/tests/parser_tests/test_microwatt_loadstore1_pp.vhd +222 -0
  118. data/tests/parser_tests/test_microwatt_logical.vhd +1 -0
  119. data/tests/parser_tests/test_microwatt_logical_pp.vhd +87 -0
  120. data/tests/parser_tests/test_microwatt_multiply.vhd +1 -0
  121. data/tests/parser_tests/test_microwatt_multiply_pp.vhd +84 -0
  122. data/tests/parser_tests/test_microwatt_multiply_tb.vhd +1 -0
  123. data/tests/parser_tests/test_microwatt_multiply_tb_pp.vhd +75 -0
  124. data/tests/parser_tests/test_microwatt_plru.vhd +1 -0
  125. data/tests/parser_tests/test_microwatt_plru_pp.vhd +46 -0
  126. data/tests/parser_tests/test_microwatt_plru_tb.vhd +1 -0
  127. data/tests/parser_tests/test_microwatt_plru_tb_pp.vhd +93 -0
  128. data/tests/parser_tests/test_microwatt_ppc_fx_insns.vhd +1 -0
  129. data/tests/parser_tests/test_microwatt_ppc_fx_insns_pp.vhd +665 -0
  130. data/tests/parser_tests/test_microwatt_register_file.vhd +1 -0
  131. data/tests/parser_tests/test_microwatt_register_file_pp.vhd +86 -0
  132. data/tests/parser_tests/test_microwatt_rotator.vhd +1 -0
  133. data/tests/parser_tests/test_microwatt_rotator_pp.vhd +149 -0
  134. data/tests/parser_tests/test_microwatt_rotator_tb.vhd +1 -0
  135. data/tests/parser_tests/test_microwatt_rotator_tb_pp.vhd +134 -0
  136. data/tests/parser_tests/test_microwatt_sim_bram.vhd +1 -0
  137. data/tests/parser_tests/test_microwatt_sim_bram_helpers.vhd +1 -0
  138. data/tests/parser_tests/test_microwatt_sim_bram_helpers_pp.vhd +52 -0
  139. data/tests/parser_tests/test_microwatt_sim_bram_pp.vhd +53 -0
  140. data/tests/parser_tests/test_microwatt_sim_console.vhd +1 -0
  141. data/tests/parser_tests/test_microwatt_sim_console_pp.vhd +43 -0
  142. data/tests/parser_tests/test_microwatt_sim_jtag.vhd +1 -0
  143. data/tests/parser_tests/test_microwatt_sim_jtag_pp.vhd +64 -0
  144. data/tests/parser_tests/test_microwatt_sim_jtag_socket.vhd +1 -0
  145. data/tests/parser_tests/test_microwatt_sim_jtag_socket_pp.vhd +36 -0
  146. data/tests/parser_tests/test_microwatt_sim_uart.vhd +1 -0
  147. data/tests/parser_tests/test_microwatt_sim_uart_pp.vhd +90 -0
  148. data/tests/parser_tests/test_microwatt_soc.vhd +1 -0
  149. data/tests/parser_tests/test_microwatt_soc_pp.vhd +195 -0
  150. data/tests/parser_tests/test_microwatt_utils.vhd +1 -0
  151. data/tests/parser_tests/test_microwatt_utils_pp.vhd +39 -0
  152. data/tests/parser_tests/test_microwatt_wishbone_arbiter.vhd +1 -0
  153. data/tests/parser_tests/test_microwatt_wishbone_arbiter_pp.vhd +54 -0
  154. data/tests/parser_tests/test_microwatt_wishbone_bram_tb.vhd +1 -0
  155. data/tests/parser_tests/test_microwatt_wishbone_bram_tb_pp.vhd +157 -0
  156. data/tests/parser_tests/test_microwatt_wishbone_bram_wrapper.vhd +1 -0
  157. data/tests/parser_tests/test_microwatt_wishbone_bram_wrapper_pp.vhd +62 -0
  158. data/tests/parser_tests/test_microwatt_wishbone_debug_master.vhd +1 -0
  159. data/tests/parser_tests/test_microwatt_wishbone_debug_master_pp.vhd +124 -0
  160. data/tests/parser_tests/test_microwatt_wishbone_types.vhd +1 -0
  161. data/tests/parser_tests/test_microwatt_wishbone_types_pp.vhd +38 -0
  162. data/tests/parser_tests/test_microwatt_writeback.vhd +1 -0
  163. data/tests/parser_tests/test_microwatt_writeback_pp.vhd +87 -0
  164. data/tests/parser_tests/test_package-1.vhd +68 -0
  165. data/tests/parser_tests/test_package-1_pp.vhd +53 -0
  166. data/tests/parser_tests/test_precedence.vhd +13 -0
  167. data/tests/parser_tests/test_precedence_pp.vhd +16 -0
  168. data/tests/parser_tests/test_selected_sig.vhd +14 -0
  169. data/tests/parser_tests/test_selected_sig_pp.vhd +10 -0
  170. data/tests/parser_tests/test_slice.vhd +15 -0
  171. data/tests/parser_tests/test_slice_pp.vhd +16 -0
  172. data/tests/parser_tests/test_tb-00.vhd +94 -0
  173. data/tests/parser_tests/test_tb-00_pp.vhd +71 -0
  174. data/tests/parser_tests/test_type_decl_02.vhd +9 -0
  175. data/tests/parser_tests/test_type_decl_02_pp.vhd +11 -0
  176. data/tests/parser_tests/test_use.vhd +7 -0
  177. data/tests/parser_tests/test_use_pp.vhd +10 -0
  178. data/tests/parser_tests/test_while_1.vhd +38 -0
  179. data/tests/parser_tests/test_while_1_pp.vhd +26 -0
  180. data/tests/parser_tests/test_with-00.vhd +21 -0
  181. data/tests/parser_tests/test_with-00_pp.vhd +12 -0
  182. data/tests/tb_gen_tests/test_accelerator.vhd +160 -0
  183. metadata +224 -0
@@ -0,0 +1 @@
1
+ ../microwatt/countzero_tb.vhdl
@@ -0,0 +1,70 @@
1
+ -- generated by Vertigo VHDL tool
2
+ library ieee;
3
+ use ieee.std_logic_1164.all;
4
+ use ieee.numeric_std.all;
5
+ library work;
6
+ use work.common.all;
7
+ use work.glibc_random.all;
8
+
9
+ entity countzero_tb is
10
+ end entity countzero_tb;
11
+
12
+ architecture behave of countzero_tb is
13
+ constant clk_period : time := 10 ns;
14
+ signal rs : std_ulogic_vector(63 downto 0);
15
+ signal is_32bit : std_ulogic;
16
+ signal count_right : std_ulogic := '0';
17
+ signal result : std_ulogic_vector(63 downto 0);
18
+ signal randno : std_ulogic_vector(63 downto 0);
19
+ signal clk : std_ulogic;
20
+ begin
21
+
22
+ zerocounter_0 : entity work.zero_counter
23
+ port map(
24
+ clk => clk,
25
+ rs => rs,
26
+ result => result,
27
+ count_right => count_right,
28
+ is_32bit => is_32bit);
29
+
30
+
31
+ clk_process : process
32
+ begin
33
+ clk <= '0';
34
+ wait clk_period / 2;
35
+ clk <= '1';
36
+ wait clk_period / 2;
37
+ end process;
38
+
39
+ stim_process : process
40
+ variable r : std_ulogic_vector(63 downto 0);
41
+ begin
42
+ report "test zero input";
43
+ rs <= (others => '0');
44
+ is_32bit <= '0';
45
+ count_right <= '0';
46
+ wait clk_period;
47
+ assert result = x"0000000000000040"
48
+ report "bad cntlzd 0 = " & to_hstring(result);
49
+ count_right <= '1';
50
+ wait clk_period;
51
+ assert result = x"0000000000000040"
52
+ report "bad cnttzd 0 = " & to_hstring(result);
53
+ is_32bit <= '1';
54
+ count_right <= '0';
55
+ wait clk_period;
56
+ assert result = x"0000000000000020"
57
+ report "bad cntlzw 0 = " & to_hstring(result);
58
+ count_right <= '1';
59
+ wait clk_period;
60
+ assert result = x"0000000000000020"
61
+ report "bad cnttzw 0 = " & to_hstring(result);
62
+ report "test cntlzd/w";
63
+ count_right <= '0';
64
+ report "test cnttzd/w";
65
+ count_right <= '1';
66
+ assert false
67
+ report "end of test" severity failure;
68
+ wait ;
69
+ end process;
70
+ end behave;
@@ -0,0 +1 @@
1
+ ../microwatt/cr_file.vhdl
@@ -0,0 +1,74 @@
1
+ -- generated by Vertigo VHDL tool
2
+ library ieee;
3
+ use ieee.std_logic_1164.all;
4
+ use ieee.numeric_std.all;
5
+ library work;
6
+ use work.common.all;
7
+
8
+ entity cr_file is
9
+ generic(
10
+ sim : booleanfalse := false);
11
+ port(
12
+ clk : in std_logic;
13
+ d_in : in decode2tocrfiletype;
14
+ d_out : out crfiletodecode2type;
15
+ w_in : in writebacktocrfiletype;
16
+ sim_dump : in std_ulogic);
17
+ end entity cr_file;
18
+
19
+ architecture behaviour of cr_file is
20
+ signal crs : std_ulogic_vector(31 downto 0) := (others => '0');
21
+ signal crs_updated : std_ulogic_vector(31 downto 0);
22
+ signal xerc : xer_common_t := xerc_init;
23
+ signal xerc_updated : xer_common_t;
24
+ begin
25
+
26
+
27
+ cr_create_0 : process(all)
28
+ variable hi : integer;
29
+ variable lo : integer := 0;
30
+ variable cr_tmp : std_ulogic_vector(31 downto 0) := (others => '0');
31
+ begin
32
+ cr_tmp := crs;
33
+ crs_updated <= cr_tmp;
34
+ if w_in.write_xerc_enable = '1' then
35
+ xerc_updated <= w_in.write_xerc_data;
36
+ else
37
+ xerc_updated <= xerc;
38
+ end if;
39
+ end process;
40
+
41
+ cr_write_0 : process(clk)
42
+ begin
43
+ if rising_edge(clk) then
44
+ if w_in.write_cr_enable = '1' then
45
+ report "writing " & to_hstring(w_in.write_cr_data) & " to cr mask " & to_hstring(w_in.write_cr_mask);
46
+ crs <= crs_updated;
47
+ end if;
48
+ if w_in.write_xerc_enable = '1' then
49
+ report "writing xerc";
50
+ xerc <= xerc_updated;
51
+ end if;
52
+ end if;
53
+ end process;
54
+
55
+ cr_read_0 : process(all)
56
+ begin
57
+ if d_in.read = '1' then
58
+ report "reading cr " & to_hstring(crs_updated);
59
+ end if;
60
+ d_out.read_cr_data <= crs_updated;
61
+ d_out.read_xerc_data <= xerc_updated;
62
+ end process;
63
+ if sim generate
64
+
65
+ dump_cr : process(all)
66
+ begin
67
+ if sim_dump = '1' then
68
+ report "cr 00000000" & to_hstring(crs);
69
+ assert false
70
+ report "end of test" severity failure;
71
+ end if;
72
+ end process;
73
+ end generate;
74
+ end behaviour;
@@ -0,0 +1 @@
1
+ ../microwatt/cr_hazard.vhdl
@@ -0,0 +1,51 @@
1
+ -- generated by Vertigo VHDL tool
2
+ library ieee;
3
+ use ieee.std_logic_1164.all;
4
+ use ieee.numeric_std.all;
5
+
6
+ entity cr_hazard is
7
+ generic(
8
+ pipeline_depth : natural2 := 2);
9
+ port(
10
+ clk : in std_ulogic;
11
+ stall_in : in std_ulogic;
12
+ cr_read_in : in std_ulogic;
13
+ cr_write_in : in std_ulogic;
14
+ stall_out : out std_ulogic);
15
+ end entity cr_hazard;
16
+
17
+ architecture behaviour of cr_hazard is
18
+
19
+ type pipeline_entry_type is record
20
+ valid : std_ulogic;
21
+ end record;
22
+ constant pipeline_entry_init : pipeline_entry_type := (valid => '0');
23
+
24
+ type pipeline_t is array(range 0 to pipeline_depth - 1) of pipeline_entry_type;
25
+ constant pipeline_t_init : pipeline_t := (others => pipeline_entry_init);
26
+ signal r : pipeline_t;
27
+ signal rin : pipeline_t := pipeline_t_init;
28
+ begin
29
+
30
+
31
+ cr_hazard0 : process(clk)
32
+ begin
33
+ if rising_edge(clk) then
34
+ if stall_in = '0' then
35
+ r <= rin;
36
+ end if;
37
+ end if;
38
+ end process;
39
+
40
+ cr_hazard1 : process(all)
41
+ variable v : pipeline_t;
42
+ begin
43
+ v := r;
44
+ stall_out <= '0';
45
+ v(0).valid := cr_write_in;
46
+ if cr_read_in = '0' then
47
+ stall_out <= '0';
48
+ end if;
49
+ rin <= v;
50
+ end process;
51
+ end behaviour;
@@ -0,0 +1 @@
1
+ ../microwatt/crhelpers.vhdl
@@ -0,0 +1,48 @@
1
+ -- generated by Vertigo VHDL tool
2
+ library ieee;
3
+ use ieee.std_logic_1164.all;
4
+ library work;
5
+ use work.common.all;
6
+
7
+ package crhelpers is
8
+
9
+ subtype crnum_t is integer range 0 to 7;
10
+
11
+ subtype crmask_t is std_ulogic_vector(7 downto 0);
12
+ function fxm_to_num(fxm : crmask_t) return crnum_t
13
+ function num_to_fxm(num : crnum_t) return crmask_t
14
+
15
+ end crhelpers;
16
+
17
+ package body crhelpers is
18
+
19
+ function fxm_to_num(fxm : crmask_t) return crnum_t is
20
+ begin
21
+ ;
22
+ return 7;
23
+ end function fxm_to_num;
24
+
25
+ function num_to_fxm(num : crnum_t) return crmask_t is
26
+ begin
27
+ case num is
28
+ when 0 =>
29
+ return "10000000";
30
+ when 1 =>
31
+ return "01000000";
32
+ when 2 =>
33
+ return "00100000";
34
+ when 3 =>
35
+ return "00010000";
36
+ when 4 =>
37
+ return "00001000";
38
+ when 5 =>
39
+ return "00000100";
40
+ when 6 =>
41
+ return "00000010";
42
+ when 7 =>
43
+ return "00000001";
44
+ when others =>
45
+ return "00000000";
46
+ end case;
47
+ end function num_to_fxm;
48
+ end crhelpers;
@@ -0,0 +1 @@
1
+ ../microwatt/dcache.vhdl
@@ -0,0 +1,481 @@
1
+ -- generated by Vertigo VHDL tool
2
+ library ieee;
3
+ use ieee.std_logic_1164.all;
4
+ use ieee.numeric_std.all;
5
+ library work;
6
+ use work.utils.all;
7
+ use work.common.all;
8
+ use work.helpers.all;
9
+ use work.wishbone_types.all;
10
+
11
+ entity dcache is
12
+ generic(
13
+ line_size : positive64 := 64;
14
+ num_lines : positive32 := 32;
15
+ num_ways : positive4 := 4);
16
+ port(
17
+ clk : in std_ulogic;
18
+ rst : in std_ulogic;
19
+ d_in : in loadstore1todcachetype;
20
+ d_out : out dcachetoloadstore1type;
21
+ stall_out : out std_ulogic;
22
+ wishbone_out : out wishbone_master_out;
23
+ wishbone_in : in wishbone_slave_out);
24
+ end entity dcache;
25
+
26
+ architecture rtl of dcache is
27
+ constant row_size : natural := wishbone_data_bits / 8;
28
+ constant row_per_line : natural := line_size / row_size;
29
+ constant bram_rows : natural := num_lines * row_per_line;
30
+ constant row_bits : natural := log2(bram_rows);
31
+ constant row_linebits : natural := log2(row_per_line);
32
+ constant line_off_bits : natural := log2(line_size);
33
+ constant row_off_bits : natural := log2(row_size);
34
+ constant index_bits : natural := log2(num_lines);
35
+ constant tag_bits : natural := 64 - line_off_bits - index_bits;
36
+ constant way_bits : natural := log2(num_ways);
37
+
38
+ subtype row_t is integer range 0 to bram_rows - 1;
39
+
40
+ subtype index_t is integer range 0 to num_lines - 1;
41
+
42
+ subtype way_t is integer range 0 to num_ways - 1;
43
+
44
+ subtype cache_row_t is std_ulogic_vector(wishbone_data_bits - 1 downto 0);
45
+
46
+ subtype cache_tag_t is std_logic_vector(tag_bits - 1 downto 0);
47
+ constant tag_ram_width : natural := tag_bits * num_ways;
48
+
49
+ subtype cache_tags_set_t is std_logic_vector(tag_ram_width - 1 downto 0);
50
+
51
+ type cache_tags_array_t is array(range index_t) of cache_tags_set_t;
52
+
53
+ subtype cache_way_valids_t is std_ulogic_vector(num_ways - 1 downto 0);
54
+
55
+ type cache_valids_t is array(range index_t) of cache_way_valids_t;
56
+ signal cache_tags : cache_tags_array_t;
57
+ signal cache_valids : cache_valids_t;
58
+ attribute ram_style : string;
59
+ attribute ram_style of cache_tags : signal is "distributed";
60
+ signal r0 : loadstore1todcachetype;
61
+
62
+ type op_t is (op_none,op_load_hit,op_load_miss,op_load_nc,op_bad,op_store_hit,op_store_miss);
63
+
64
+ type state_t is (idle,reload_wait_ack,finish_ld_miss,store_wait_ack,nc_load_wait_ack);
65
+
66
+ type reg_stage_1_t is record
67
+ req : loadstore1todcachetype;
68
+ hit_way : way_t;
69
+ hit_load_valid : std_ulogic;
70
+ slow_data : std_ulogic_vector(63 downto 0);
71
+ slow_valid : std_ulogic;
72
+ stcx_fail : std_ulogic;
73
+ state : state_t;
74
+ wb : wishbone_master_out;
75
+ store_way : way_t;
76
+ store_row : row_t;
77
+ store_index : index_t;
78
+ end record;
79
+ signal r1 : reg_stage_1_t;
80
+
81
+ type reservation_t is record
82
+ valid : std_ulogic;
83
+ addr : std_ulogic_vector(63 downto line_off_bits);
84
+ end record;
85
+ signal reservation : reservation_t;
86
+ signal req_index : index_t;
87
+ signal req_row : row_t;
88
+ signal req_hit_way : way_t;
89
+ signal req_tag : cache_tag_t;
90
+ signal req_op : op_t;
91
+ signal req_data : std_ulogic_vector(63 downto 0);
92
+ signal req_laddr : std_ulogic_vector(63 downto 0);
93
+ signal early_req_row : row_t;
94
+ signal cancel_store : std_ulogic;
95
+ signal set_rsrv : std_ulogic;
96
+ signal clear_rsrv : std_ulogic;
97
+
98
+ type cache_ram_out_t is array(range way_t) of cache_row_t;
99
+ signal cache_out : cache_ram_out_t;
100
+
101
+ type plru_out_t is array(range index_t) of std_ulogic_vector(way_bits - 1 downto 0);
102
+ signal plru_victim : plru_out_t;
103
+ signal replace_way : way_t;
104
+ signal bus_sel : std_ulogic_vector(7 downto 0);
105
+
106
+ function get_index(addr : std_ulogic_vector(63 downto 0)) return index_t is
107
+ begin
108
+ return to_integer(unsigned(addr(63 - tag_bits downto line_off_bits)));
109
+ end function get_index;
110
+
111
+ function get_row(addr : std_ulogic_vector(63 downto 0)) return row_t is
112
+ begin
113
+ return to_integer(unsigned(addr(63 - tag_bits downto row_off_bits)));
114
+ end function get_row;
115
+
116
+ function is_last_row_addr(addr : wishbone_addr_type) return boolean is
117
+ constant ones : std_ulogic_vector(row_linebits - 1 downto 0) := (others => '1');
118
+ begin
119
+ return addr(line_off_bits - 1 downto row_off_bits) = ones;
120
+ end function is_last_row_addr;
121
+
122
+ function is_last_row(row : row_t) return boolean is
123
+ variable row_v : std_ulogic_vector(row_bits - 1 downto 0);
124
+ constant ones : std_ulogic_vector(row_linebits - 1 downto 0) := (others => '1');
125
+ begin
126
+ row_v := std_ulogic_vector(to_unsigned(row,row_bits));
127
+ return row_v(row_linebits - 1 downto 0) = ones;
128
+ end function is_last_row;
129
+
130
+ function next_row_addr(addr : wishbone_addr_type) return std_ulogic_vector is
131
+ variable row_idx : std_ulogic_vector(row_linebits - 1 downto 0);
132
+ variable result : wishbone_addr_type;
133
+ begin
134
+ row_idx := addr(line_off_bits - 1 downto row_off_bits);
135
+ row_idx := std_ulogic_vector(unsigned(row_idx) + 1);
136
+ result := addr;
137
+ result(line_off_bits - 1 downto row_off_bits) := row_idx;
138
+ return result;
139
+ end function next_row_addr;
140
+
141
+ function next_row(row : row_t) return row_t is
142
+ variable row_v : std_ulogic_vector(row_bits - 1 downto 0);
143
+ variable row_idx : std_ulogic_vector(row_linebits - 1 downto 0);
144
+ variable result : std_ulogic_vector(row_bits - 1 downto 0);
145
+ begin
146
+ row_v := std_ulogic_vector(to_unsigned(row,row_bits));
147
+ row_idx := row_v(row_linebits - 1 downto 0);
148
+ row_v(row_linebits - 1 downto 0) := std_ulogic_vector(unsigned(row_idx) + 1);
149
+ return to_integer(unsigned(row_v));
150
+ end function next_row;
151
+
152
+ function get_tag(addr : std_ulogic_vector(63 downto 0)) return cache_tag_t is
153
+ begin
154
+ return addr(63 downto 64 - tag_bits);
155
+ end function get_tag;
156
+
157
+ function read_tag(way : way_t;tagset : cache_tags_set_t) return cache_tag_t is
158
+ begin
159
+ return tagset((way + 1) * tag_bits - 1 downto way * tag_bits);
160
+ end function read_tag;
161
+
162
+ procedure write_tag(
163
+ way : in way_t;
164
+ tagset : inout cache_tags_set_t;
165
+ tag : cache_tag_t) is
166
+ begin
167
+ tagset((way + 1) * tag_bits - 1 downto way * tag_bits) := tag;
168
+ end write_tag;
169
+ begin
170
+
171
+ assert line_size mod row_size = 0
172
+ report "line_size not multiple of row_size" severity failure;
173
+ assert ispow2(line_size)
174
+ report "line_size not power of 2" severity failure;
175
+ assert ispow2(num_lines)
176
+ report "num_lines not power of 2" severity failure;
177
+ assert ispow2(row_per_line)
178
+ report "row_per_line not power of 2" severity failure;
179
+ assert (row_bits = index_bits + row_linebits)
180
+ report "geometry bits don't add up" severity failure;
181
+ assert (line_off_bits = row_off_bits + row_linebits)
182
+ report "geometry bits don't add up" severity failure;
183
+ assert (64 = tag_bits + index_bits + line_off_bits)
184
+ report "geometry bits don't add up" severity failure;
185
+ assert (64 = tag_bits + row_bits + row_off_bits)
186
+ report "geometry bits don't add up" severity failure;
187
+ assert (64 = wishbone_data_bits)
188
+ report "can't yet handle a wishbone width that isn't 64-bits" severity failure;
189
+ if num_ways > 1 generate
190
+ for i in 0 to num_lines - 1 generate
191
+ plru : entity work.plru
192
+ port map(
193
+ clk => clk,
194
+ rst => rst,
195
+ acc => plru_acc,
196
+ acc_en => plru_acc_en,
197
+ lru => plru_out);
198
+
199
+
200
+ process(req_index,req_op,req_hit_way,plru_out)
201
+ begin
202
+ if (req_op = op_load_hit or req_op = op_store_hit) and req_index = i then
203
+ plru_acc_en <= '1';
204
+ else
205
+ plru_acc_en <= '0';
206
+ end if;
207
+ plru_acc <= std_ulogic_vector(to_unsigned(req_hit_way,way_bits));
208
+ plru_victim(i) <= plru_out;
209
+ end process;
210
+ end generate;
211
+ end generate;
212
+
213
+ stage_0 : process(clk)
214
+ begin
215
+ if rising_edge(clk) then
216
+ if rst = '1' then
217
+ r0.valid <= '0';
218
+ elsif stall_out = '0' then
219
+ r0 <= d_in;
220
+ end if;
221
+ end if;
222
+ end process;
223
+
224
+ dcache_request : process(all)
225
+ variable is_hit : std_ulogic;
226
+ variable hit_way : way_t;
227
+ variable op : op_t;
228
+ variable tmp : std_ulogic_vector(63 downto 0);
229
+ variable data : std_ulogic_vector(63 downto 0);
230
+ variable opsel : std_ulogic_vector(3 downto 0);
231
+ variable go : std_ulogic;
232
+ begin
233
+ req_index <= get_index(r0.addr);
234
+ req_row <= get_row(r0.addr);
235
+ req_tag <= get_tag(r0.addr);
236
+ go := r0.valid and stall_out;
237
+ req_laddr <= r0.addr(63 downto line_off_bits) & (line_off_bits - 1 downto 0 => '0');
238
+ hit_way := 0;
239
+ is_hit := '0';
240
+ req_hit_way <= hit_way;
241
+ replace_way <= to_integer(unsigned(plru_victim(req_index)));
242
+ opsel := go & r0.load & r0.nc & is_hit;
243
+ case opsel is
244
+ when "1101" =>
245
+ op := op_load_hit;
246
+ when "1100" =>
247
+ op := op_load_miss;
248
+ when "1110" =>
249
+ op := op_load_nc;
250
+ when "1001" =>
251
+ op := op_store_hit;
252
+ when "1000" =>
253
+ op := op_store_miss;
254
+ when "1010" =>
255
+ op := op_store_miss;
256
+ when "1011" =>
257
+ op := op_bad;
258
+ when "1111" =>
259
+ op := op_bad;
260
+ when others =>
261
+ op := op_none;
262
+ end case;
263
+ req_op <= op;
264
+ if stall_out = '0' then
265
+ early_req_row <= get_row(d_in.addr);
266
+ else
267
+ early_req_row <= req_row;
268
+ end if;
269
+ end process;
270
+ wishbone_out <= r1.wb;
271
+ stall_out <= '1' when r1.state /= idle else '0';
272
+
273
+ reservation_comb : process(all)
274
+ begin
275
+ cancel_store <= '0';
276
+ set_rsrv <= '0';
277
+ clear_rsrv <= '0';
278
+ if stall_out = '0' and r0.valid = '1' and r0.reserve = '1' then
279
+ if r0.load = '1' then
280
+ set_rsrv <= '1';
281
+ else
282
+ clear_rsrv <= '1';
283
+ if reservation.valid = '0' or r0.addr(63 downto line_off_bits) /= reservation.addr then
284
+ cancel_store <= '1';
285
+ end if;
286
+ end if;
287
+ end if;
288
+ end process;
289
+
290
+ reservation_reg : process(clk)
291
+ begin
292
+ if rising_edge(clk) then
293
+ if rst = '1' or clear_rsrv = '1' then
294
+ reservation.valid <= '0';
295
+ elsif set_rsrv = '1' then
296
+ reservation.valid <= '1';
297
+ reservation.addr <= r0.addr(63 downto line_off_bits);
298
+ end if;
299
+ end if;
300
+ end process;
301
+
302
+ writeback_control : process(all)
303
+ begin
304
+ d_out.valid <= '0';
305
+ d_out.data <= cache_out(r1.hit_way);
306
+ d_out.store_done <= '0';
307
+ assert (r1.slow_valid and r1.stcx_fail) /= '1'
308
+ report "unexpected slow_valid collision with stcx_fail" severity failure;
309
+ assert ((r1.slow_valid or r1.stcx_fail) and r1.hit_load_valid) /= '1'
310
+ report "unexpected hit_load_delayed collision with slow_valid" severity failure;
311
+ if r1.hit_load_valid = '1' then
312
+ report "completing load hit";
313
+ d_out.valid <= '1';
314
+ end if;
315
+ if r1.slow_valid = '1' then
316
+ if r1.req.load then
317
+ d_out.data <= r1.slow_data;
318
+ end if;
319
+ d_out.store_done <= '1';
320
+ report "completing store or load miss";
321
+ d_out.valid <= '1';
322
+ end if;
323
+ if r1.stcx_fail = '1' then
324
+ d_out.store_done <= '0';
325
+ d_out.valid <= '1';
326
+ end if;
327
+ end process;
328
+ for i in 0 to num_ways - 1 generate
329
+ way : entity work.cache_ram
330
+ port map(
331
+ clk => clk,
332
+ rd_en => do_read,
333
+ rd_addr => rd_addr,
334
+ rd_data => dout,
335
+ wr_en => do_write,
336
+ wr_sel => wr_sel,
337
+ wr_addr => wr_addr,
338
+ wr_data => wr_data);
339
+
340
+
341
+ process(all)
342
+ variable tmp_adr : std_ulogic_vector(63 downto 0);
343
+ variable reloading : boolean;
344
+ begin
345
+ do_read <= '1';
346
+ rd_addr <= std_ulogic_vector(to_unsigned(early_req_row,row_bits));
347
+ cache_out(i) <= dout;
348
+ if r1.state = idle then
349
+ wr_addr <= std_ulogic_vector(to_unsigned(req_row,row_bits));
350
+ wr_data <= r0.data;
351
+ wr_sel <= r0.byte_sel;
352
+ else
353
+ wr_data <= wishbone_in.dat;
354
+ wr_sel <= (others => '1');
355
+ wr_addr <= std_ulogic_vector(to_unsigned(r1.store_row,row_bits));
356
+ end if;
357
+ do_write <= '0';
358
+ reloading := r1.state = reload_wait_ack;
359
+ if reloading and wishbone_in.ack = '1' and r1.store_way = i then
360
+ do_write <= '1';
361
+ end if;
362
+ if req_op = op_store_hit and req_hit_way = i and cancel_store = '0' then
363
+ assert reloading
364
+ report "store hit while in state:" & state_t'image(r1.state) severity failure;
365
+ do_write <= '1';
366
+ end if;
367
+ end process;
368
+ end generate;
369
+
370
+ dcache_fast_hit : process(clk)
371
+ begin
372
+ if rising_edge(clk) then
373
+ if req_op /= op_none and stall_out = '0' then
374
+ r1.req <= r0;
375
+ report "op:" & op_t'image(req_op) & " addr:" & to_hstring(r0.addr) & " nc:" & std_ulogic'image(r0.nc) & " idx:" & integer'image(req_index) & " tag:" & to_hstring(req_tag) & " way: " & integer'image(req_hit_way);
376
+ end if;
377
+ if req_op = op_load_hit then
378
+ r1.hit_way <= req_hit_way;
379
+ r1.hit_load_valid <= '1';
380
+ else
381
+ r1.hit_load_valid <= '0';
382
+ end if;
383
+ end if;
384
+ end process;
385
+
386
+ dcache_slow : process(clk)
387
+ variable tagset : cache_tags_set_t;
388
+ variable stbs_done : boolean;
389
+ begin
390
+ if rising_edge(clk) then
391
+ if rst = '1' then
392
+ ;
393
+ r1.state <= idle;
394
+ r1.slow_valid <= '0';
395
+ r1.wb.cyc <= '0';
396
+ r1.wb.stb <= '0';
397
+ r1.wb.adr <= (others => '0');
398
+ else
399
+ r1.slow_valid <= '0';
400
+ r1.stcx_fail <= '0';
401
+ case r1.state is
402
+ when idle =>
403
+ case req_op is
404
+ when op_load_hit =>
405
+ when op_load_miss =>
406
+ report "cache miss addr:" & to_hstring(r0.addr) & " idx:" & integer'image(req_index) & " way:" & integer'image(replace_way) & " tag:" & to_hstring(req_tag);
407
+ cache_valids(req_index)(replace_way) <= '0';
408
+ r1.store_index <= req_index;
409
+ r1.store_way <= replace_way;
410
+ r1.store_row <= get_row(req_laddr);
411
+ r1.wb.adr <= req_laddr(r1.wb.adr'left downto 0);
412
+ r1.wb.sel <= (others => '1');
413
+ r1.wb.we <= '0';
414
+ r1.wb.cyc <= '1';
415
+ r1.wb.stb <= '1';
416
+ r1.state <= reload_wait_ack;
417
+ when op_load_nc =>
418
+ r1.wb.sel <= r0.byte_sel;
419
+ r1.wb.adr <= r0.addr(r1.wb.adr'left downto 3) & "000";
420
+ r1.wb.cyc <= '1';
421
+ r1.wb.stb <= '1';
422
+ r1.wb.we <= '0';
423
+ r1.state <= nc_load_wait_ack;
424
+ when op_store_hit | op_store_miss =>
425
+ r1.wb.sel <= r0.byte_sel;
426
+ r1.wb.adr <= r0.addr(r1.wb.adr'left downto 3) & "000";
427
+ r1.wb.dat <= r0.data;
428
+ if cancel_store = '0' then
429
+ r1.wb.cyc <= '1';
430
+ r1.wb.stb <= '1';
431
+ r1.wb.we <= '1';
432
+ r1.state <= store_wait_ack;
433
+ else
434
+ r1.stcx_fail <= '1';
435
+ r1.state <= idle;
436
+ end if;
437
+ when op_none =>
438
+ when op_bad =>
439
+ end case;
440
+ when reload_wait_ack =>
441
+ stbs_done := r1.wb.stb = '0';
442
+ if wishbone_in.stall = '0' and stbs_done then
443
+ if is_last_row_addr(r1.wb.adr) then
444
+ r1.wb.stb <= '0';
445
+ stbs_done := true;
446
+ end if;
447
+ r1.wb.adr <= next_row_addr(r1.wb.adr);
448
+ end if;
449
+ if wishbone_in.ack = '1' then
450
+ if r1.store_row = get_row(r1.req.addr) then
451
+ r1.slow_data <= wishbone_in.dat;
452
+ end if;
453
+ if stbs_done and is_last_row(r1.store_row) then
454
+ r1.wb.cyc <= '0';
455
+ cache_valids(r1.store_index)(r1.store_way) <= '1';
456
+ r1.state <= finish_ld_miss;
457
+ end if;
458
+ r1.store_row <= next_row(r1.store_row);
459
+ end if;
460
+ when finish_ld_miss =>
461
+ r1.slow_valid <= '1';
462
+ r1.state <= idle;
463
+ report "completing miss !";
464
+ when store_wait_ack | nc_load_wait_ack =>
465
+ if wishbone_in.stall = '0' then
466
+ r1.wb.stb <= '0';
467
+ end if;
468
+ if wishbone_in.ack = '1' then
469
+ if r1.state = nc_load_wait_ack then
470
+ r1.slow_data <= wishbone_in.dat;
471
+ end if;
472
+ r1.state <= idle;
473
+ r1.slow_valid <= '1';
474
+ r1.wb.cyc <= '0';
475
+ r1.wb.stb <= '0';
476
+ end if;
477
+ end case;
478
+ end if;
479
+ end if;
480
+ end process;
481
+ end rtl;