Commit 02110307cc103e7cff52036a139f190ca8245ab5

Authored by zinsser
1 parent 006b1b933c

Synthesis and STA automation

Showing 18 changed files with 307 additions and 304 deletions Side-by-side Diff

mips_cpu/Makefile View file @ 0211030
1   -.PHONY: clean verilate simulate dump
  1 +.PHONY: clean verilate simulate dump wave
2 2  
3   -s.v: t.v
4   - yosys -s mips_core.ys -l yosys.log -t
5   -
6   -t.v: memory_interfaces.sv mips_core/alu.sv mips_core/branch_controller.sv mips_core/cache_bank.sv mips_core/d_cache.sv mips_core/decoder.sv mips_core/fetch_unit.sv mips_core/forward_unit.sv mips_core/glue_circuits.sv mips_core/hazard_controller.sv mips_core/i_cache.sv mips_core/mips_core.sv mips_core/mips_core.svh mips_core/mips_core_interfaces.sv mips_core/mips_core_pkg.sv mips_core/pipeline_registers.sv mips_core/reg_file.sv mips_cpu_pkg.sv pass_done_interface.sv
7   - ~/Downloads/sv2v-Linux-v0.0.4/sv2v -Imips_core mips_cpu_pkg.sv memory_interfaces.sv pass_done_interface.sv mips_core/*.sv | grep -v import | grep -v "\$$error" | grep -v "\$$stop" | grep -v "\$$fwrite" | grep -v "\$$fflush" > t.v
8   -
9 3 verilate:
10   - verilator --cc --exe --build --trace-fst -DSIMULATION -Imips_core -f verilator_files --top-module mips_core verilator_main.cpp memory.cpp memory_driver.cpp -Wno-fatal
  4 + bash -c "source $(CSE148_TOOLS)/oss-cad-suite/environment && verilator --cc --exe --build --trace-fst -DSIMULATION -Imips_core -f verilator_files --top-module mips_core verilator_main.cpp memory.cpp memory_driver.cpp -Wno-fatal"
11 5  
12 6 simulate:
13 7 obj_dir/Vmips_core
14 8  
15 9 dump:
16 10 obj_dir/Vmips_core -d
  11 +
  12 +wave:
  13 + gtkwave simx.fst
17 14  
18 15 clean:
19 16 rm -rf obj_dir/
mips_cpu/mips_core.sdc View file @ 0211030
1   -create_clock -period 10 -name clk [get_ports clk]
2   -set_input_delay -max -clock clk 1 [get_ports rst_n]
3   -set_input_delay -min -clock clk -1 [get_ports rst_n]
4   -set_output_delay -max -clock clk 1 [get_ports rst_n]
5   -set_output_delay -min -clock clk -1 [get_ports rst_n]
6   -set_input_delay -max -clock clk 1 [get_ports i_cache_read_control_done]
7   -set_input_delay -min -clock clk -1 [get_ports i_cache_read_control_done]
8   -set_output_delay -max -clock clk 1 [get_ports i_cache_read_control_done]
9   -set_output_delay -min -clock clk -1 [get_ports i_cache_read_control_done]
10   -set_input_delay -max -clock clk 1 [get_ports i_cache_read_user_data]
11   -set_input_delay -min -clock clk -1 [get_ports i_cache_read_user_data]
12   -set_output_delay -max -clock clk 1 [get_ports i_cache_read_user_data]
13   -set_output_delay -min -clock clk -1 [get_ports i_cache_read_user_data]
14   -set_input_delay -max -clock clk 1 [get_ports i_cache_read_user_available]
15   -set_input_delay -min -clock clk -1 [get_ports i_cache_read_user_available]
16   -set_output_delay -max -clock clk 1 [get_ports i_cache_read_user_available]
17   -set_output_delay -min -clock clk -1 [get_ports i_cache_read_user_available]
18   -set_input_delay -max -clock clk 1 [get_ports i_cache_read_control_base]
19   -set_input_delay -min -clock clk -1 [get_ports i_cache_read_control_base]
20   -set_output_delay -max -clock clk 1 [get_ports i_cache_read_control_base]
21   -set_output_delay -min -clock clk -1 [get_ports i_cache_read_control_base]
22   -set_input_delay -max -clock clk 1 [get_ports i_cache_read_control_length]
23   -set_input_delay -min -clock clk -1 [get_ports i_cache_read_control_length]
24   -set_output_delay -max -clock clk 1 [get_ports i_cache_read_control_length]
25   -set_output_delay -min -clock clk -1 [get_ports i_cache_read_control_length]
26   -set_input_delay -max -clock clk 1 [get_ports i_cache_read_control_go]
27   -set_input_delay -min -clock clk -1 [get_ports i_cache_read_control_go]
28   -set_output_delay -max -clock clk 1 [get_ports i_cache_read_control_go]
29   -set_output_delay -min -clock clk -1 [get_ports i_cache_read_control_go]
30   -set_input_delay -max -clock clk 1 [get_ports i_cache_read_user_re]
31   -set_input_delay -min -clock clk -1 [get_ports i_cache_read_user_re]
32   -set_output_delay -max -clock clk 1 [get_ports i_cache_read_user_re]
33   -set_output_delay -min -clock clk -1 [get_ports i_cache_read_user_re]
34   -set_input_delay -max -clock clk 1 [get_ports d_cache_write_control_done]
35   -set_input_delay -min -clock clk -1 [get_ports d_cache_write_control_done]
36   -set_output_delay -max -clock clk 1 [get_ports d_cache_write_control_done]
37   -set_output_delay -min -clock clk -1 [get_ports d_cache_write_control_done]
38   -set_input_delay -max -clock clk 1 [get_ports d_cache_write_user_full]
39   -set_input_delay -min -clock clk -1 [get_ports d_cache_write_user_full]
40   -set_output_delay -max -clock clk 1 [get_ports d_cache_write_user_full]
41   -set_output_delay -min -clock clk -1 [get_ports d_cache_write_user_full]
42   -set_input_delay -max -clock clk 1 [get_ports d_cache_write_control_base]
43   -set_input_delay -min -clock clk -1 [get_ports d_cache_write_control_base]
44   -set_output_delay -max -clock clk 1 [get_ports d_cache_write_control_base]
45   -set_output_delay -min -clock clk -1 [get_ports d_cache_write_control_base]
46   -set_input_delay -max -clock clk 1 [get_ports d_cache_write_control_length]
47   -set_input_delay -min -clock clk -1 [get_ports d_cache_write_control_length]
48   -set_output_delay -max -clock clk 1 [get_ports d_cache_write_control_length]
49   -set_output_delay -min -clock clk -1 [get_ports d_cache_write_control_length]
50   -set_input_delay -max -clock clk 1 [get_ports d_cache_write_control_go]
51   -set_input_delay -min -clock clk -1 [get_ports d_cache_write_control_go]
52   -set_output_delay -max -clock clk 1 [get_ports d_cache_write_control_go]
53   -set_output_delay -min -clock clk -1 [get_ports d_cache_write_control_go]
54   -set_input_delay -max -clock clk 1 [get_ports d_cache_write_user_we]
55   -set_input_delay -min -clock clk -1 [get_ports d_cache_write_user_we]
56   -set_output_delay -max -clock clk 1 [get_ports d_cache_write_user_we]
57   -set_output_delay -min -clock clk -1 [get_ports d_cache_write_user_we]
58   -set_input_delay -max -clock clk 1 [get_ports d_cache_write_user_data]
59   -set_input_delay -min -clock clk -1 [get_ports d_cache_write_user_data]
60   -set_output_delay -max -clock clk 1 [get_ports d_cache_write_user_data]
61   -set_output_delay -min -clock clk -1 [get_ports d_cache_write_user_data]
62   -set_input_delay -max -clock clk 1 [get_ports d_cache_read_control_done]
63   -set_input_delay -min -clock clk -1 [get_ports d_cache_read_control_done]
64   -set_output_delay -max -clock clk 1 [get_ports d_cache_read_control_done]
65   -set_output_delay -min -clock clk -1 [get_ports d_cache_read_control_done]
66   -set_input_delay -max -clock clk 1 [get_ports d_cache_read_user_data]
67   -set_input_delay -min -clock clk -1 [get_ports d_cache_read_user_data]
68   -set_output_delay -max -clock clk 1 [get_ports d_cache_read_user_data]
69   -set_output_delay -min -clock clk -1 [get_ports d_cache_read_user_data]
70   -set_input_delay -max -clock clk 1 [get_ports d_cache_read_user_available]
71   -set_input_delay -min -clock clk -1 [get_ports d_cache_read_user_available]
72   -set_output_delay -max -clock clk 1 [get_ports d_cache_read_user_available]
73   -set_output_delay -min -clock clk -1 [get_ports d_cache_read_user_available]
74   -set_input_delay -max -clock clk 1 [get_ports d_cache_read_control_base]
75   -set_input_delay -min -clock clk -1 [get_ports d_cache_read_control_base]
76   -set_output_delay -max -clock clk 1 [get_ports d_cache_read_control_base]
77   -set_output_delay -min -clock clk -1 [get_ports d_cache_read_control_base]
78   -set_input_delay -max -clock clk 1 [get_ports d_cache_read_control_length]
79   -set_input_delay -min -clock clk -1 [get_ports d_cache_read_control_length]
80   -set_output_delay -max -clock clk 1 [get_ports d_cache_read_control_length]
81   -set_output_delay -min -clock clk -1 [get_ports d_cache_read_control_length]
82   -set_input_delay -max -clock clk 1 [get_ports d_cache_read_control_go]
83   -set_input_delay -min -clock clk -1 [get_ports d_cache_read_control_go]
84   -set_output_delay -max -clock clk 1 [get_ports d_cache_read_control_go]
85   -set_output_delay -min -clock clk -1 [get_ports d_cache_read_control_go]
86   -set_input_delay -max -clock clk 1 [get_ports d_cache_read_user_re]
87   -set_input_delay -min -clock clk -1 [get_ports d_cache_read_user_re]
88   -set_output_delay -max -clock clk 1 [get_ports d_cache_read_user_re]
89   -set_output_delay -min -clock clk -1 [get_ports d_cache_read_user_re]
90   -set_input_delay -max -clock clk 1 [get_ports pass_done_value]
91   -set_input_delay -min -clock clk -1 [get_ports pass_done_value]
92   -set_output_delay -max -clock clk 1 [get_ports pass_done_value]
93   -set_output_delay -min -clock clk -1 [get_ports pass_done_value]
94   -set_input_delay -max -clock clk 1 [get_ports pass_done_code]
95   -set_input_delay -min -clock clk -1 [get_ports pass_done_code]
96   -set_output_delay -max -clock clk 1 [get_ports pass_done_code]
97   -set_output_delay -min -clock clk -1 [get_ports pass_done_code]
mips_cpu/mips_core.ys View file @ 0211030
1   -read_liberty -lib /home/zinsser/cse148/FreePDK45/osu_soc/lib/files/gscl45nm.lib
2   -read_liberty -lib /home/zinsser/cse148/baseline/mips_cpu/rams/build/sram_32_16_freepdk45_TT_1p0V_25C.lib
3   -read_verilog t.v
4   -synth -top mips_core -flatten
5   -dfflibmap -liberty /home/zinsser/cse148/FreePDK45/osu_soc/lib/files/gscl45nm.lib
6   -abc -liberty /home/zinsser/cse148/FreePDK45/osu_soc/lib/files/gscl45nm.lib -constr mips_core.constr -D 5000
7   -opt_clean
8   -
9   -write_verilog -attr2comment s.v
10   -stat -liberty /home/zinsser/cse148/FreePDK45/osu_soc/lib/files/gscl45nm.lib -liberty /home/zinsser/cse148/baseline/mips_cpu/rams/build/sram_32_16_freepdk45_TT_1p0V_25C.lib
mips_cpu/mips_core/alu.sv View file @ 0211030
... ... @@ -97,7 +97,12 @@
97 97 ALUCTL_BGEZ: out.branch_outcome = in.op1 >= signed'(0) ? TAKEN : NOT_TAKEN;
98 98 ALUCTL_BLTZ: out.branch_outcome = in.op1 < signed'(0) ? TAKEN : NOT_TAKEN;
99 99  
100   - default: $display("%m (%t) Illegal ALUCTL code %b", $time, in.alu_ctl);
  100 + default:
  101 + begin
  102 + `ifdef SIMULATION
  103 + $display("%m (%t) Illegal ALUCTL code %b", $time, in.alu_ctl);
  104 + `endif
  105 + end
101 106 endcase
102 107 end
103 108 end
mips_cpu/mips_core/cache_bank.sv View file @ 0211030
... ... @@ -34,20 +34,25 @@
34 34 // the read output (old_data) should be presented at the output port.
35 35 logic new_data_flag;
36 36  
37   - // cache_bank_core #(DATA_WIDTH, ADDR_WIDTH)
38   - // BANK_CORE (
39   - // .clk, .i_we, .i_waddr, .i_raddr, .i_wdata,
40   - // .o_rdata(old_data)
41   - // );
  37 + generate
  38 + if (ADDR_WIDTH < 4) begin
  39 + // OpenRAM requires at least 16 rows
  40 + // Use register based structure for shallow RAMs
  41 + cache_bank_core #(DATA_WIDTH, ADDR_WIDTH)
  42 + BANK_CORE (
  43 + .clk, .i_we, .i_waddr, .i_raddr, .i_wdata,
  44 + .o_rdata(old_data)
  45 + );
  46 + end else begin
  47 + sram #(.DATA_WIDTH(DATA_WIDTH), .ADDR_WIDTH(ADDR_WIDTH)) BANK_CORE (
  48 + // Port 0: W
  49 + .clk0(clk), .csb0(~i_we), .addr0(i_waddr), .din0(i_wdata),
  50 + // Port 1: R
  51 + .clk1(clk), .csb1('0), .addr1(i_raddr), .dout1(old_data)
  52 + );
  53 + end
  54 + endgenerate
42 55  
43   - // sram_32_16_freepdk45 BANK_CORE (
44   - sram #(DATA_WIDTH, ADDR_WIDTH) BANK_CORE (
45   - // Port 0: W
46   - .clk0(clk), .csb0(~i_we), .addr0(i_waddr), .din0(i_wdata),
47   - // Port 1: R
48   - .clk1(clk), .csb1('0), .addr1(i_raddr), .dout1(old_data)
49   - );
50   -
51 56 assign o_rdata = new_data_flag ? new_data : old_data;
52 57  
53 58 always_ff @(posedge clk)
... ... @@ -76,65 +81,7 @@
76 81 end
77 82 endmodule
78 83  
79   -module cache_bank_sp #(parameter DATA_WIDTH = 32, parameter ADDR_WIDTH = 4)(
80   - input clk, // Clock
81   - input i_we, // Write enable
82   - input logic [DATA_WIDTH - 1 : 0] i_wdata, // Write data
83   - input logic [ADDR_WIDTH - 1 : 0] i_waddr, i_raddr, // Write/read address
84   - output logic o_rvalid,
85   - output logic [DATA_WIDTH - 1 : 0] o_rdata // Read data
86   -);
87   -
88   - // A register to store new_data
89   - logic [DATA_WIDTH - 1 : 0] new_data;
90   -
91   - // The registered output of cache_bank_core_sp
92   - logic rvalid;
93   - logic [DATA_WIDTH - 1 : 0] rdata;
94   -
95   - // A flag to determine whether the last cycle write data (new_data) or
96   - // the read output (old_data) should be presented at the output port.
97   - logic new_data_flag;
98   -
99   - cache_bank_core_sp #(DATA_WIDTH, ADDR_WIDTH)
100   - BANK_CORE (
101   - .clk, .i_we, .i_waddr, .i_raddr, .i_wdata,
102   - .o_rvalid(rvalid),
103   - .o_rdata(rdata)
104   - );
105   -
106   - assign o_rvalid = new_data_flag | rvalid;
107   - assign o_rdata = new_data_flag ? new_data : rdata;
108   -
109   - always_ff @(posedge clk)
110   - begin
111   - new_data <= i_wdata;
112   - new_data_flag <= i_we & (i_raddr == i_waddr);
113   - end
114   -endmodule
115   -
116   -module cache_bank_core_sp #(parameter DATA_WIDTH = 32, parameter ADDR_WIDTH = 4)(
117   - input clk, // Clock
118   - input i_we, // Write enable
119   - input logic [DATA_WIDTH - 1 : 0] i_wdata, // Write data
120   - input logic [ADDR_WIDTH - 1 : 0] i_waddr, i_raddr, // Write/read address
121   - output logic o_rvalid,
122   - output logic [DATA_WIDTH - 1 : 0] o_rdata // Read data
123   -);
124   - localparam DEPTH = 1 << ADDR_WIDTH;
125   -
126   - logic [DATA_WIDTH - 1 : 0] data [DEPTH];
127   -
128   - always_ff @(posedge clk)
129   - begin
130   - if (i_we)
131   - data[i_waddr] <= i_wdata;
132   - else
133   - o_rdata <= data[i_raddr];
134   - o_rvalid <= !i_we;
135   - end
136   -endmodule
137   -
  84 +`ifdef SIMULATION
138 85 // OpenRAM SRAM model
139 86 module sram(
140 87 // Port 0: W
... ... @@ -207,4 +154,5 @@
207 154 end
208 155  
209 156 endmodule
  157 +`endif
mips_cpu/mips_core/d_cache.sv View file @ 0211030
... ... @@ -238,51 +238,30 @@
238 238  
239 239 always_comb
240 240 begin
  241 + next_state = state;
241 242 unique case (state)
242 243 STATE_READY:
243   - begin
244 244 if (miss)
245   - begin
246 245 if (valid_bits[i_index] & dirty_bits[i_index])
247 246 next_state = STATE_FLUSH_REQUEST;
248 247 else
249 248 next_state = STATE_REFILL_REQUEST;
250   - end
251   - else
252   - next_state = state;
253   - end
254 249  
255 250 STATE_FLUSH_REQUEST:
256   - begin
257 251 if (mem_write_address.AWREADY)
258 252 next_state = STATE_FLUSH_DATA;
259   - else
260   - next_state = state;
261   - end
262 253  
263 254 STATE_FLUSH_DATA:
264   - begin
265 255 if (last_flush_word && mem_write_data.WREADY)
266 256 next_state = STATE_REFILL_REQUEST;
267   - else
268   - next_state = state;
269   - end
270 257  
271 258 STATE_REFILL_REQUEST:
272   - begin
273 259 if (mem_read_address.ARREADY)
274 260 next_state = STATE_REFILL_DATA;
275   - else
276   - next_state = state;
277   - end
278 261  
279 262 STATE_REFILL_DATA:
280   - begin
281 263 if (last_refill_word)
282 264 next_state = STATE_READY;
283   - else
284   - next_state = state;
285   - end
286 265 endcase
287 266 end
288 267  
mips_cpu/mips_core/decoder.sv View file @ 0211030
... ... @@ -49,7 +49,7 @@
49 49 decoder_output_ifc.out out
50 50 );
51 51  
52   - task uses_rs;
  52 + task rs;
53 53 begin
54 54 // Only set uses_rs if it is not register zero
55 55 out.uses_rs = |i_inst.data[25:21];
... ... @@ -57,7 +57,7 @@
57 57 end
58 58 endtask
59 59  
60   - task uses_rt;
  60 + task rt;
61 61 begin
62 62 // Only set uses_rt if it is not register zero
63 63 out.uses_rt = |i_inst.data[20:16];
... ... @@ -74,7 +74,7 @@
74 74 end
75 75 endtask
76 76  
77   - task uses_immediate_raw;
  77 + task immediate_raw;
78 78 input [31:0] immediate;
79 79 begin
80 80 out.uses_immediate = 1'b1;
81 81  
82 82  
83 83  
... ... @@ -82,19 +82,19 @@
82 82 end
83 83 endtask
84 84  
85   - task uses_immediate_zero_extend;
86   - uses_immediate_raw(32'(unsigned'(i_inst.data[15:0])));
  85 + task immediate_zero_extend;
  86 + immediate_raw(32'(unsigned'(i_inst.data[15:0])));
87 87 endtask
88 88  
89   - task uses_immediate_signed_extend;
90   - uses_immediate_raw(32'(signed'(i_inst.data[15:0])));
  89 + task immediate_signed_extend;
  90 + immediate_raw(32'(signed'(i_inst.data[15:0])));
91 91 endtask
92 92  
93   - task uses_immediate_shamt;
94   - uses_immediate_raw(32'(unsigned'(i_inst.data[10:6])));
  93 + task immediate_shamt;
  94 + immediate_raw(32'(unsigned'(i_inst.data[10:6])));
95 95 endtask
96 96  
97   - task uses_rw_raw;
  97 + task rw_raw;
98 98 input [4:0] rw;
99 99 begin
100 100 // Only set uses_rw if it is not register zero
101 101  
102 102  
103 103  
104 104  
105 105  
... ... @@ -103,43 +103,43 @@
103 103 end
104 104 endtask
105 105  
106   - task uses_rw_rtype;
107   - uses_rw_raw(i_inst.data[15:11]);
  106 + task rw_rtype;
  107 + rw_raw(i_inst.data[15:11]);
108 108 endtask
109 109  
110   - task uses_rw_itype;
111   - uses_rw_raw(i_inst.data[20:16]);
  110 + task rw_itype;
  111 + rw_raw(i_inst.data[20:16]);
112 112 endtask
113 113  
114 114 task typical_rtype;
115 115 begin
116   - uses_rs();
117   - uses_rt();
118   - uses_rw_rtype();
  116 + rs();
  117 + rt();
  118 + rw_rtype();
119 119 end
120 120 endtask
121 121  
122 122 task shamt_rtype;
123 123 begin
124 124 route_rt_to_rs();
125   - uses_rw_rtype();
126   - uses_immediate_shamt();
  125 + rw_rtype();
  126 + immediate_shamt();
127 127 end
128 128 endtask
129 129  
130 130 task signed_extend_itype;
131 131 begin
132   - uses_rs();
133   - uses_rw_itype();
134   - uses_immediate_signed_extend();
  132 + rs();
  133 + rw_itype();
  134 + immediate_signed_extend();
135 135 end
136 136 endtask
137 137  
138 138 task zero_extend_itype;
139 139 begin
140   - uses_rs();
141   - uses_rw_itype();
142   - uses_immediate_zero_extend();
  140 + rs();
  141 + rw_itype();
  142 + immediate_zero_extend();
143 143 end
144 144 endtask
145 145  
... ... @@ -274,7 +274,7 @@
274 274 6'h08: // jr
275 275 begin
276 276 out.alu_ctl = ALUCTL_NOP; // jr does not use alu
277   - uses_rs();
  277 + rs();
278 278 out.is_branch_jump = 1'b1;
279 279 out.is_jump = 1'b1;
280 280 out.is_jump_reg = 1'b1;
... ... @@ -283,9 +283,9 @@
283 283 6'h09: //jalr
284 284 begin
285 285 out.alu_ctl = ALUCTL_OR;
286   - uses_rs();
287   - uses_rw_raw(ra); // jalr always write to ra (31)
288   - uses_immediate_raw(32'(unsigned'(i_pc.pc)) + 8);
  286 + rs();
  287 + rw_raw(ra); // jalr always write to ra (31)
  288 + immediate_raw(32'(unsigned'(i_pc.pc)) + 8);
289 289 out.is_branch_jump = 1'b1;
290 290 out.is_jump = 1'b1;
291 291 out.is_jump_reg = 1'b1;
292 292  
293 293  
294 294  
295 295  
296 296  
297 297  
298 298  
299 299  
300 300  
... ... @@ -293,31 +293,41 @@
293 293  
294 294 6'h18: // mul
295 295 begin
  296 + `ifdef SIMULTION
296 297 $error("%m (%t) mul not supported. Treated as a NOP. PC=0x%x", $time, i_pc.pc);
  298 + `endif
297 299 out.valid = 1'b0;
298 300 end
299 301  
300 302 6'h19: //mulu
301 303 begin
  304 + `ifdef SIMULTION
302 305 $error("%m (%t) mulu not supported. Treated as a NOP. PC=0x%x", $time, i_pc.pc);
  306 + `endif
303 307 out.valid = 1'b0;
304 308 end
305 309  
306 310 6'h1a: //div
307 311 begin
  312 + `ifdef SIMULTION
308 313 $error("%m (%t) div not supported. Treated as a NOP. PC=0x%x", $time, i_pc.pc);
  314 + `endif
309 315 out.valid = 1'b0;
310 316 end
311 317  
312 318 6'h1b: //divu
313 319 begin
  320 + `ifdef SIMULTION
314 321 $error("%m (%t) divu not supported. Treated as a NOP. PC=0x%x", $time, i_pc.pc);
  322 + `endif
315 323 out.valid = 1'b0;
316 324 end
317 325  
318 326 default:
319 327 begin
  328 + `ifdef SIMULTION
320 329 $error("%m (%t) unknown R-type funct code %b. Treated as a NOP. PC=0x%x", $time, i_inst.data[5:0], i_pc.pc);
  330 + `endif
321 331 out.valid = 1'b0;
322 332 end
323 333 endcase
324 334  
... ... @@ -368,15 +378,15 @@
368 378 6'h0f: //lui Implemented as 0 | Immediate
369 379 begin
370 380 out.alu_ctl = ALUCTL_OR;
371   - uses_rw_itype();
372   - uses_immediate_raw({i_inst.data[15:0], 16'h0000});
  381 + rw_itype();
  382 + immediate_raw({i_inst.data[15:0], 16'h0000});
373 383 end
374 384  
375 385 6'h04: //beq
376 386 begin
377 387 out.alu_ctl = ALUCTL_BEQ;
378   - uses_rs();
379   - uses_rt();
  388 + rs();
  389 + rt();
380 390 out.is_branch_jump = 1'b1;
381 391 out.branch_target = i_pc.pc + `ADDR_WIDTH'd4 + `ADDR_WIDTH'(signed'(i_inst.data[15:0]) << 2);
382 392 end
... ... @@ -384,8 +394,8 @@
384 394 6'h05: //bne
385 395 begin
386 396 out.alu_ctl = ALUCTL_BNE;
387   - uses_rs();
388   - uses_rt();
  397 + rs();
  398 + rt();
389 399 out.is_branch_jump = 1'b1;
390 400 out.branch_target = i_pc.pc + `ADDR_WIDTH'd4 + `ADDR_WIDTH'(signed'(i_inst.data[15:0]) << 2);
391 401 end
... ... @@ -393,8 +403,8 @@
393 403 6'h06: //blez
394 404 begin
395 405 out.alu_ctl = ALUCTL_BLEZ;
396   - uses_rs();
397   - uses_rt();
  406 + rs();
  407 + rt();
398 408 out.is_branch_jump = 1'b1;
399 409 out.branch_target = i_pc.pc + `ADDR_WIDTH'd4 + `ADDR_WIDTH'(signed'(i_inst.data[15:0]) << 2);
400 410 end
... ... @@ -405,8 +415,8 @@
405 415 out.alu_ctl = ALUCTL_BGEZ;
406 416 else
407 417 out.alu_ctl = ALUCTL_BLTZ;
408   - uses_rs();
409   - uses_rt();
  418 + rs();
  419 + rt();
410 420 out.is_branch_jump = 1'b1;
411 421 out.branch_target = i_pc.pc + `ADDR_WIDTH'd4 + `ADDR_WIDTH'(signed'(i_inst.data[15:0]) << 2);
412 422 end
... ... @@ -414,8 +424,8 @@
414 424 6'h07: //bgtz
415 425 begin
416 426 out.alu_ctl = ALUCTL_BGTZ;
417   - uses_rs();
418   - uses_rt();
  427 + rs();
  428 + rt();
419 429 out.is_branch_jump = 1'b1;
420 430 out.branch_target = i_pc.pc + `ADDR_WIDTH'd4 + `ADDR_WIDTH'(signed'(i_inst.data[15:0]) << 2);
421 431 end
... ... @@ -431,8 +441,8 @@
431 441 6'h03: // jal
432 442 begin
433 443 out.alu_ctl = ALUCTL_OR;
434   - uses_rw_raw(ra); // jal always write to ra (31)
435   - uses_immediate_raw(32'(unsigned'(i_pc.pc)) + 8);
  444 + rw_raw(ra); // jal always write to ra (31)
  445 + immediate_raw(32'(unsigned'(i_pc.pc)) + 8);
436 446 out.is_branch_jump = 1'b1;
437 447 out.is_jump = 1'b1;
438 448 out.branch_target = {i_inst.data[`ADDR_WIDTH - 3: 0], 2'b00};
439 449  
440 450  
441 451  
442 452  
443 453  
444 454  
445 455  
... ... @@ -440,25 +450,33 @@
440 450  
441 451 6'h20: //lb
442 452 begin
  453 + `ifdef SIMULTION
443 454 $error("%m (%t) lb not supported. Treated as a NOP. PC=0x%x", $time, i_pc.pc);
  455 + `endif
444 456 out.valid = 1'b0;
445 457 end
446 458  
447 459 6'h24: //lbu
448 460 begin
  461 + `ifdef SIMULTION
449 462 $error("%m (%t) lbu not supported. Treated as a NOP. PC=0x%x", $time, i_pc.pc);
  463 + `endif
450 464 out.valid = 1'b0;
451 465 end
452 466  
453 467 6'h21: //lh
454 468 begin
  469 + `ifdef SIMULTION
455 470 $error("%m (%t) lh not supported. Treated as a NOP. PC=0x%x", $time, i_pc.pc);
  471 + `endif
456 472 out.valid = 1'b0;
457 473 end
458 474  
459 475 6'h25: //lhu
460 476 begin
  477 + `ifdef SIMULTION
461 478 $error("%m (%t) lhu not supported. Treated as a NOP. PC=0x%x", $time, i_pc.pc);
  479 + `endif
462 480 out.valid = 1'b0;
463 481 end
464 482  
465 483  
466 484  
467 485  
... ... @@ -472,13 +490,17 @@
472 490  
473 491 6'h28: //sb
474 492 begin
  493 + `ifdef SIMULTION
475 494 $error("%m (%t) sb not supported. Treated as a NOP. PC=0x%x", $time, i_pc.pc);
  495 + `endif
476 496 out.valid = 1'b0;
477 497 end
478 498  
479 499 6'h29: //sh
480 500 begin
  501 + `ifdef SIMULTION
481 502 $error("%m (%t) sh not supported. Treated as a NOP. PC=0x%x", $time, i_pc.pc);
  503 + `endif
482 504 out.valid = 1'b0;
483 505 end
484 506  
... ... @@ -487,9 +509,9 @@
487 509 out.alu_ctl = ALUCTL_ADD;
488 510 out.is_mem_access = 1'b1;
489 511 out.mem_action = WRITE;
490   - uses_rs();
491   - uses_rt();
492   - uses_immediate_signed_extend();
  512 + rs();
  513 + rt();
  514 + immediate_signed_extend();
493 515 end
494 516  
495 517 6'h10: //mtc0
496 518  
497 519  
498 520  
499 521  
... ... @@ -498,24 +520,26 @@
498 520 5'h17:
499 521 begin
500 522 out.alu_ctl = ALUCTL_MTC0_PASS;
501   - uses_rt();
  523 + rt();
502 524 end
503 525  
504 526 5'h18:
505 527 begin
506 528 out.alu_ctl = ALUCTL_MTC0_FAIL;
507   - uses_rt();
  529 + rt();
508 530 end
509 531  
510 532 5'h19:
511 533 begin
512 534 out.alu_ctl = ALUCTL_MTC0_DONE;
513   - uses_rt();
  535 + rt();
514 536 end
515 537  
516 538 default:
517 539 begin
  540 + `ifdef SIMULTION
518 541 $error("%m (%t) unknown MTC0 value 0x%x. Treated as a NOP. PC=0x%x", $time, i_inst.data[15:11], i_pc.pc);
  542 + `endif
519 543 out.valid = 1'b0;
520 544 end
521 545 endcase
522 546  
... ... @@ -523,8 +547,9 @@
523 547  
524 548 default:
525 549 begin
  550 + `ifdef SIMULTION
526 551 $error("%m (%t) unknown opcode %b. Treated as a NOP. PC=0x%x", $time, i_inst.data[31:26], i_pc.pc);
527   - $stop;
  552 + `endif
528 553 out.valid = 1'b0;
529 554 end
530 555 endcase
mips_cpu/mips_core/i_cache.sv View file @ 0211030
... ... @@ -184,28 +184,17 @@
184 184  
185 185 always_comb
186 186 begin
  187 + next_state = state;
187 188 unique case (state)
188 189 STATE_READY:
189   - begin
190 190 if (miss)
191 191 next_state = STATE_REFILL_REQUEST;
192   - else
193   - next_state = state;
194   - end
195 192 STATE_REFILL_REQUEST:
196   - begin
197 193 if (mem_read_address.ARREADY)
198 194 next_state = STATE_REFILL_DATA;
199   - else
200   - next_state = state;
201   - end
202 195 STATE_REFILL_DATA:
203   - begin
204 196 if (last_refill_word)
205 197 next_state = STATE_READY;
206   - else
207   - next_state = state;
208   - end
209 198 endcase
210 199 end
211 200  
mips_cpu/rams/.gitignore View file @ 0211030
1   -__pycache__/
2   -build/
mips_cpu/rams/config.py View file @ 0211030
1   -# Data word size
2   -word_size = 32
3   -# Number of words in the memory
4   -num_words = 16
5   -
6   -# Technology to use in $OPENRAM_TECH
7   -tech_name = "freepdk45"
8   -
9   -num_rw_ports = 0
10   -num_r_ports = 1
11   -num_w_ports = 1
12   -
13   -# You can use the technology nominal corner only
14   -nominal_corner_only = True
15   -# Or you can specify particular corners
16   -# Process corners to characterize
17   -# process_corners = ["SS", "TT", "FF"]
18   -# Voltage corners to characterize
19   -# supply_voltages = [ 3.0, 3.3, 3.5 ]
20   -# Temperature corners to characterize
21   -# temperatures = [ 0, 25 100]
22   -
23   -# Output directory for the results
24   -output_path = "build"
25   -# Output file base name
26   -output_name = "sram_{0}_{1}_{2}_analytical".format(word_size,num_words,tech_name)
27   -
28   -# Disable analytical models for full characterization (WARNING: slow!)
29   -# analytical_delay = False
mips_cpu/synth/.gitignore View file @ 0211030
  1 +__pycache__/
  2 +build/
  3 +*.json
  4 +*.log
  5 +*.v
  6 +configs.mk
  7 +synthesis.ys
  8 +timing.sta
mips_cpu/synth/Makefile View file @ 0211030
  1 +.PHONY: clean all rams syn sta
  2 +
  3 +configs=
  4 +ifneq (clean,$(MAKECMDGOALS))
  5 +include configs.mk
  6 +endif
  7 +
  8 +ram_targets=$(configs:%=build/sram_%_freepdk45_analytical_TT_1p0V_25C.lib)
  9 +
  10 +all: netlist.v
  11 +
  12 +mips_core.v: ../mips_core/*.sv
  13 + $(CSE148_TOOLS)/sv2v-Linux/sv2v -Imips_core ../mips_core/*.sv > $@
  14 +
  15 +hierarchy.json: mips_core.v
  16 + bash -c "source $(CSE148_TOOLS)/oss-cad-suite/environment && yosys -s hierarchy.ys -l hierarchy.log -t"
  17 +
  18 +configs.mk synthesis.ys sram.v timing.sta: hierarchy.json generate.py
  19 + python3 generate.py
  20 +
  21 +rams: $(ram_targets)
  22 +
  23 +build/sram_%_freepdk45_analytical_TT_1p0V_25C.lib : config.py
  24 + env RAM_CONFIG="$*" \
  25 + FREEPDK45=$(CSE148_TOOLS)/FreePDK45 \
  26 + OPENRAM_HOME=$(CSE148_TOOLS)/OpenRAM/compiler \
  27 + OPENRAM_TECH=$(CSE148_TOOLS)/OpenRAM/technology \
  28 + $(CSE148_TOOLS)/venv/bin/python3 $(CSE148_TOOLS)/OpenRAM/compiler/openram.py config
  29 +
  30 +netlist.v: mips_core.v $(ram_targets) synthesis.ys
  31 + bash -c "source ~/cse148/oss-cad-suite/environment && yosys -s synthesis.ys -l synthesis.log -t"
  32 +
  33 +syn: netlist.v
  34 +
  35 +sta: netlist.v timing.sta $(ram_targets)
  36 + $(CSE148_TOOLS)/OpenSTA/app/sta timing.sta
  37 +
  38 +clean:
  39 + rm -rf build
  40 + rm -f *.log
  41 + rm -f *.json
  42 + rm -f *.v
  43 + rm -f configs.mk
  44 + rm -f synthesis.ys
  45 + rm -f timing.sta
mips_cpu/synth/config.py View file @ 0211030
  1 +import os
  2 +
  3 +word_size, num_words = os.environ["RAM_CONFIG"].split("_")
  4 +
  5 +# Data word size
  6 +word_size = int(word_size)
  7 +# Number of words in the memory
  8 +num_words = int(num_words)
  9 +
  10 +# Technology to use in $OPENRAM_TECH
  11 +tech_name = "freepdk45"
  12 +
  13 +num_rw_ports = 0
  14 +num_r_ports = 1
  15 +num_w_ports = 1
  16 +
  17 +# You can use the technology nominal corner only
  18 +nominal_corner_only = True
  19 +# Or you can specify particular corners
  20 +# Process corners to characterize
  21 +# process_corners = ["SS", "TT", "FF"]
  22 +# Voltage corners to characterize
  23 +# supply_voltages = [ 3.0, 3.3, 3.5 ]
  24 +# Temperature corners to characterize
  25 +# temperatures = [ 0, 25 100]
  26 +
  27 +# Output directory for the results
  28 +output_path = "build"
  29 +# Output file base name
  30 +output_name = "sram_{0}_{1}_{2}_analytical".format(word_size,num_words,tech_name)
  31 +
  32 +# Disable analytical models for full characterization (WARNING: slow!)
  33 +# analytical_delay = False
mips_cpu/synth/generate.py View file @ 0211030
  1 +import json
  2 +import os
  3 +
  4 +liberty = f"{os.environ['CSE148_TOOLS']}/FreePDK45/osu_soc/lib/files/gscl45nm.lib"
  5 +
  6 +
  7 +def parse_hierarchy(file_name):
  8 + with open(file_name) as f:
  9 + h = json.load(f)
  10 +
  11 + configs = set()
  12 + for module_name, module in h["modules"].items():
  13 + for cell in module["cells"].values():
  14 + if cell["type"] == "sram":
  15 + addr_width = int(cell["parameters"]["ADDR_WIDTH"], 2)
  16 + data_width = int(cell["parameters"]["DATA_WIDTH"], 2)
  17 + depth = 1 << addr_width
  18 + print(f"Found sram {data_width}x{depth} in {module_name}")
  19 + configs.add((addr_width, data_width, depth))
  20 + return configs
  21 +
  22 +def generate_makefile(configs):
  23 + with open("configs.mk", "w") as f:
  24 + f.write("configs=")
  25 + f.write(" ".join(f"{w}_{h}" for _, w, h in configs))
  26 +
  27 +def generate_sram_mapping(configs):
  28 + with open("sram.v", "w") as f:
  29 + f.write(f"""
  30 +
  31 +module sram(
  32 +// Port 0: W
  33 + clk0,csb0,addr0,din0,
  34 +// Port 1: R
  35 + clk1,csb1,addr1,dout1
  36 + );
  37 +
  38 + parameter DATA_WIDTH = 32;
  39 + parameter ADDR_WIDTH = 4;
  40 +
  41 + input clk0, csb0;
  42 + input [ADDR_WIDTH-1:0] addr0;
  43 + input [DATA_WIDTH-1:0] din0;
  44 + input clk1, csb1;
  45 + input [ADDR_WIDTH-1:0] addr1;
  46 + output [DATA_WIDTH-1:0] dout1;
  47 +
  48 + generate
  49 +""")
  50 + for a, w, h in configs:
  51 + f.write(f"""
  52 + if (ADDR_WIDTH == {a} && DATA_WIDTH == {w})
  53 + sram_{w}_{h}_freepdk45_analytical core (.*);
  54 +""")
  55 +
  56 + f.write("""
  57 + endgenerate
  58 +endmodule
  59 +
  60 +""")
  61 +
  62 +def generate_yosys_script(configs):
  63 + with open("synthesis.ys", "w") as f:
  64 + f.write(f"read_liberty -lib {liberty}\n")
  65 + for _, w, h in configs:
  66 + f.write(f"read_liberty -lib build/sram_{w}_{h}_freepdk45_analytical_TT_1p0V_25C.lib\n")
  67 + f.write(f"""
  68 +read_verilog mips_core.v
  69 +read_verilog -sv sram.v
  70 +synth -top mips_core -flatten
  71 +dfflibmap -liberty {liberty}
  72 +abc -liberty {liberty} -constr mips_core.constr -D 5000
  73 +opt_clean
  74 +
  75 +write_verilog -attr2comment netlist.v
  76 +stat -liberty {liberty}""")
  77 + for _, w, h in configs:
  78 + f.write(f" -liberty build/sram_{w}_{h}_freepdk45_analytical_TT_1p0V_25C.lib")
  79 +
  80 +def generate_sta_script(configs):
  81 + with open("timing.sta", "w") as f:
  82 + f.write(f"read_liberty {liberty}\n")
  83 + for _, w, h in configs:
  84 + f.write(f"read_liberty build/sram_{w}_{h}_freepdk45_analytical_TT_1p0V_25C.lib\n")
  85 + f.write(f"""
  86 +read_verilog netlist.v
  87 +link_design mips_core
  88 +read_sdc mips_core.sdc
  89 +report_checks
  90 +report_clock_min_period -include_port_paths
  91 +exit
  92 +""")
  93 +
  94 +if __name__ == "__main__":
  95 + configs = parse_hierarchy("hierarchy.json")
  96 +
  97 + generate_makefile(configs)
  98 + generate_sram_mapping(configs)
  99 + generate_yosys_script(configs)
  100 + generate_sta_script(configs)
mips_cpu/synth/hierarchy.ys View file @ 0211030
  1 +read_verilog mips_core.v
  2 +blackbox sram
  3 +hierarchy -top mips_core
  4 +proc
  5 +write_json hierarchy.json
mips_cpu/synth/mips_core.constr View file @ 0211030
  1 +set_driving_cell INVX1
  2 +set_load 0.015
mips_cpu/synth/mips_core.sdc View file @ 0211030
  1 +create_clock -period 10 -name clk [get_ports clk]
  2 +set_input_delay -max -clock clk 1 [all_inputs]
  3 +set_input_delay -min -clock clk -1 [all_inputs]
  4 +set_output_delay -max -clock clk 1 [all_outputs]
  5 +set_output_delay -min -clock clk -1 [all_outputs]
mips_cpu/verilator_main.cpp View file @ 0211030
... ... @@ -128,7 +128,7 @@
128 128 std::cout << "\n!! [" << std::dec << main_time << "] expected write back mismatches"
129 129 << "\n!! [" << std::dec << main_time << "] expected addr=" << std::hex << expected_addr
130 130 << " data=" << expected_data
131   - << "\n!! [" << std::dec << main_time << "] actual addr=" << addr
  131 + << "\n!! [" << std::dec << main_time << "] actual addr=" << std::hex << addr
132 132 << " data=" << data << std::endl;
133 133 std::raise(SIGINT);
134 134 }