Change how constants are plumbed through the hierarchy. Some small cleanups of variable declaration order etc

This commit is contained in:
Luke Wren 2021-05-21 03:23:44 +01:00
parent 6dad4e20bb
commit 5de4f01aae
13 changed files with 106 additions and 310 deletions

View File

@ -1,7 +1,7 @@
DO WHAT THE FUCK YOU WANT TO AND DON'T BLAME US PUBLIC LICENSE
Version 3, April 2008
Copyright (C) 2020 Luke Wren
Copyright (C) 2021 Luke Wren
Everyone is permitted to copy and distribute verbatim or modified
copies of this license document and accompanying software, and

View File

@ -30,20 +30,21 @@
module hazard5_muldiv_seq #(
parameter XLEN = 32,
parameter UNROLL = 1,
parameter W_CTR = $clog2(XLEN + 1) // do not modify
parameter W_CTR = $clog2(XLEN + 1), // do not modify
`include "hazard5_width_const.vh"
) (
input wire clk,
input wire rst_n,
input wire [2:0] op,
input wire op_vld,
output wire op_rdy,
input wire op_kill,
input wire [XLEN-1:0] op_a,
input wire [XLEN-1:0] op_b,
input wire clk,
input wire rst_n,
input wire [W_MULOP-1:0] op,
input wire op_vld,
output wire op_rdy,
input wire op_kill,
input wire [XLEN-1:0] op_a,
input wire [XLEN-1:0] op_b,
output wire [XLEN-1:0] result_h, // mulh* or rem*
output wire [XLEN-1:0] result_l, // mul or div*
output wire result_vld
output wire [XLEN-1:0] result_h, // mulh* or rem*
output wire [XLEN-1:0] result_l, // mul or div*
output wire result_vld
);
`include "hazard5_ops.vh"

View File

@ -1,72 +0,0 @@
/**********************************************************************
* DO WHAT THE FUCK YOU WANT TO AND DON'T BLAME US PUBLIC LICENSE *
* Version 3, April 2008 *
* *
* Copyright (C) 2018 Luke Wren *
* *
* Everyone is permitted to copy and distribute verbatim or modified *
* copies of this license document and accompanying software, and *
* changing either is allowed. *
* *
* TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION *
* *
* 0. You just DO WHAT THE FUCK YOU WANT TO. *
* 1. We're NOT RESPONSIBLE WHEN IT DOESN'T FUCKING WORK. *
* *
*********************************************************************/
module hazard5_shift_1bit_seq #(
parameter W_DATA = 32,
parameter W_SHAMT = 5
) (
input wire clk,
input wire rst_n,
input wire [W_DATA-1:0] din,
input wire din_vld, // can be asserted at any time, we always respond
input wire [W_SHAMT-1:0] shamt,
input wire right_nleft,
input wire arith,
output wire [W_DATA-1:0] dout,
output wire dout_vld,
);
reg [W_DATA-1:0] accum;
reg [W_DATA-1:0] accum_next;
reg [W_SHAMT-1:0] shamt_remaining;
reg flipped;
// Handle actual shifting
wire sext = arith && accum[W_DATA - 1];
always @ (*) begin: shift_unit
accum_next = accum;
if (din_vld) begin
accum_next = din;
end else if (shamt_remaining) begin
if (right_nleft)
accum_next = {sext, accum[W_DATA-1:1]};
else
accum_next = {accum << 1};
end
end
// No reset on datapath
always @ (posedge clk)
accum <= accum_next;
always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin
shamt_remaining <= {W_SHAMT{1'b0}};
end else if (din_vld) begin
shamt_remaining <= shamt;
end else begin
shamt_remaining <= shamt_remaining - |shamt_remaining;
end
end
assign dout_vld = shamt_remaining == 0;
assign dout = accum;
endmodule

View File

@ -1,106 +0,0 @@
/**********************************************************************
* DO WHAT THE FUCK YOU WANT TO AND DON'T BLAME US PUBLIC LICENSE *
* Version 3, April 2008 *
* *
* Copyright (C) 2018 Luke Wren *
* *
* Everyone is permitted to copy and distribute verbatim or modified *
* copies of this license document and accompanying software, and *
* changing either is allowed. *
* *
* TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION *
* *
* 0. You just DO WHAT THE FUCK YOU WANT TO. *
* 1. We're NOT RESPONSIBLE WHEN IT DOESN'T FUCKING WORK. *
* *
*********************************************************************/
// Implement the three shifts using a single log-sequential shifter.
// On each clock, the shifter can left-shift by a power-of-two amount (arith or
// logical), OR it can reverse the accumulator.
//
// The accumulator is wired in reverse to the output. So the sequences are:
// - Right shift: flip, then shift. Output wiring flips again. Internal left-shifts
// are effectively right shifts.
// - Left shift: perform shift ops, then flip, so that reversed output cancels.
//
// An additional cycle is consumed to load the input into the accumulator; this
// simplifies muxing. In total, a shift consumes between 2 and 7 cycles on a
// 32-bit machine, depending on the bit weight of shamt.
module hazard5_shift_log_seq #(
parameter W_DATA = 32,
parameter W_SHAMT = 5
) (
input wire clk,
input wire rst_n,
input wire [W_DATA-1:0] din,
input wire din_vld, // can be asserted at any time, we always respond
input wire [W_SHAMT-1:0] shamt,
input wire right_nleft,
input wire arith,
output reg [W_DATA-1:0] dout,
output reg dout_vld,
);
reg [W_DATA-1:0] accum;
reg [W_DATA-1:0] accum_next;
reg [W_SHAMT-1:0] shamt_remaining;
reg flipped;
// Handle actual shifting
wire flip = !flipped && (right_nleft || ~|shamt_remaining);
wire sext = arith && accum[0]; // "Left arithmetic" shifting
always @ (*) begin: shift_unit
integer i;
accum_next = accum;
// The following is a priority mux tree (honest) which the synthesis tool should balance
if (din_vld) begin
accum_next = din;
end else if (flip) begin
for (i = 0; i < W_DATA; i = i + 1)
accum_next[i] = accum[W_DATA - 1 - i];
end else if (shamt_remaining) begin
// Smallest shift first
for (i = 0; i < W_SHAMT; i = i + 1) begin
if (shamt_remaining[i] && ~|(shamt_remaining & ~({W_SHAMT{1'b1}} << i))) begin
accum_next = (accum << (1 << i)) |
({W_DATA{sext}} & ~({W_DATA{1'b1}} << (1 << i)));
end
end
end
end
// No reset on datapath
always @ (posedge clk)
accum <= accum_next;
// State machine
always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin
shamt_remaining <= {W_SHAMT{1'b0}};
flipped <= 1'b0;
end else if (din_vld) begin
shamt_remaining <= shamt;
flipped <= 1'b0;
end else begin
if (flip)
flipped <= 1'b1;
else
shamt_remaining <= shamt_remaining & {shamt_remaining - 1'b1};
end
end
always @ (*) begin: connect_output
dout_vld = flipped && ~|shamt_remaining;
integer i;
for (i = 0; i < W_DATA; i = i + 1)
dout[i] = accum[W_DATA - 1 - i];
end
endmodule

View File

@ -0,0 +1,17 @@
// Pass-through of parameters defined in hazard5_config.vh, so that these can
// be set at instantiation rather than editing the config file, and will flow
// correctly down through the hierarchy.
.RESET_VECTOR (RESET_VECTOR),
.MTVEC_INIT (MTVEC_INIT),
.EXTENSION_C (EXTENSION_C),
.EXTENSION_M (EXTENSION_M),
.CSR_M_MANDATORY (CSR_M_MANDATORY),
.CSR_M_TRAP (CSR_M_TRAP),
.CSR_COUNTER (CSR_COUNTER),
.REDUCED_BYPASS (REDUCED_BYPASS),
.MULDIV_UNROLL (MULDIV_UNROLL),
.MUL_FAST (MUL_FAST),
.MTVEC_WMASK (MTVEC_WMASK),
.W_ADDR (W_ADDR),
.W_DATA (W_DATA)

View File

@ -17,6 +17,8 @@
module hazard5_core #(
`include "hazard5_config.vh"
,
`include "hazard5_width_const.vh"
) (
// Global signals
input wire clk,
@ -70,11 +72,6 @@ module hazard5_core #(
//synthesis translate_on
`endif
localparam N_REGS = 32;
// should be localparam but ISIM can't cope
parameter W_REGADDR = $clog2(N_REGS);
localparam NOP_INSTR = 32'h13; // addi x0, x0, 0
wire flush_d_x;
wire d_stall;
@ -112,11 +109,8 @@ wire f_mem_size;
assign bus_hsize_i = f_mem_size ? HSIZE_WORD : HSIZE_HWORD;
hazard5_frontend #(
.EXTENSION_C(EXTENSION_C),
.W_ADDR(W_ADDR),
.W_DATA(32),
.FIFO_DEPTH(2),
.RESET_VECTOR(RESET_VECTOR)
`include "hazard5_config_inst.vh"
) frontend (
.clk (clk),
.rst_n (rst_n),
@ -190,13 +184,7 @@ wire [1:0] dx_csr_wtype;
wire dx_csr_w_imm;
hazard5_decode #(
.EXTENSION_C (EXTENSION_C),
.EXTENSION_M (EXTENSION_M),
.HAVE_CSR (CSR_M_MANDATORY || CSR_M_TRAP || CSR_COUNTER),
.W_ADDR (W_ADDR),
.W_DATA (W_DATA),
.RESET_VECTOR (RESET_VECTOR),
.W_REGADDR (W_REGADDR)
`include "hazard5_config_inst.vh"
) inst_hazard5_decode (
.clk (clk),
.rst_n (rst_n),
@ -399,13 +387,7 @@ wire [W_DATA-1:0] x_csr_rdata;
hazard5_csr #(
.XLEN (W_DATA),
.CSR_M_MANDATORY (CSR_M_MANDATORY),
.CSR_M_TRAP (CSR_M_TRAP),
.CSR_COUNTER (CSR_COUNTER),
.EXTENSION_C (EXTENSION_C),
.EXTENSION_M (EXTENSION_M),
.MTVEC_WMASK (MTVEC_WMASK),
.MTVEC_INIT (MTVEC_INIT)
`include "hazard5_config_inst.vh"
) inst_hazard5_csr (
.clk (clk),
.rst_n (rst_n),
@ -699,7 +681,7 @@ hazard5_regfile_1w2r #(
`else
.RESET_REGS(0),
`endif
.N_REGS(N_REGS),
.N_REGS(32),
.W_DATA(W_DATA)
) inst_regfile_1w2r (
.clk (clk),

View File

@ -76,17 +76,7 @@ wire [W_DATA-1:0] core_rdata_d;
hazard5_core #(
.RESET_VECTOR (RESET_VECTOR),
.EXTENSION_C (EXTENSION_C),
.EXTENSION_M (EXTENSION_M),
.MULDIV_UNROLL (MULDIV_UNROLL),
.MUL_FAST (MUL_FAST),
.CSR_M_MANDATORY (CSR_M_MANDATORY),
.CSR_M_TRAP (CSR_M_TRAP),
.CSR_COUNTER (CSR_COUNTER),
.MTVEC_WMASK (MTVEC_WMASK),
.MTVEC_INIT (MTVEC_INIT),
.REDUCED_BYPASS (REDUCED_BYPASS)
`include "hazard5_config_inst.vh"
) core (
.clk (clk),
.rst_n (rst_n),

View File

@ -89,17 +89,7 @@ wire [W_DATA-1:0] core_rdata_d;
hazard5_core #(
.RESET_VECTOR (RESET_VECTOR),
.EXTENSION_C (EXTENSION_C),
.EXTENSION_M (EXTENSION_M),
.MULDIV_UNROLL (MULDIV_UNROLL),
.MUL_FAST (MUL_FAST),
.CSR_M_MANDATORY (CSR_M_MANDATORY),
.CSR_M_TRAP (CSR_M_TRAP),
.CSR_COUNTER (CSR_COUNTER),
.MTVEC_WMASK (MTVEC_WMASK),
.MTVEC_INIT (MTVEC_INIT),
.REDUCED_BYPASS (REDUCED_BYPASS)
`include "hazard5_config_inst.vh"
) core (
.clk (clk),
.rst_n (rst_n),

View File

@ -21,16 +21,10 @@
module hazard5_csr #(
parameter XLEN = 32, // Must be 32
parameter CSR_M_MANDATORY = 1, // Include mandatory M-mode CSRs e.g. misa, marchid
parameter CSR_M_TRAP = 1, // Include M-mode trap setup/handling CSRs
parameter CSR_COUNTER = 1, // Include counter/timer CSRs
parameter EXTENSION_C = 0, // For misa
parameter EXTENSION_M = 0, // For misa
parameter MTVEC_WMASK = 32'hfffff000, // Save gates by making trap vector base partially fixed (legal, as it's WARL)
parameter MTVEC_INIT = 32'h0,// Initial value of trap vector base
parameter W_COUNTER = 64 // This *should* be 64, but can be reduced to save gates.
parameter W_COUNTER = 64, // This *should* be 64, but can be reduced to save gates.
// The full 64 bits is writeable, so high-word increment can
// be implemented in software, and a narrower hw counter used
`include "hazard5_config.vh"
) (
input wire clk,
input wire rst_n,

View File

@ -16,13 +16,9 @@
*****************************************************************************/
module hazard5_decode #(
parameter EXTENSION_C = 1, // compressed instruction extension
parameter EXTENSION_M = 1, // mul/div/mod instruction extension
parameter HAVE_CSR = 0,
parameter W_ADDR = 32,
parameter W_DATA = 32,
parameter RESET_VECTOR = 32'h0,
parameter W_REGADDR = 5
`include "hazard5_config.vh"
,
`include "hazard5_width_const.vh"
) (
input wire clk,
input wire rst_n,
@ -67,15 +63,39 @@ module hazard5_decode #(
output reg [2:0] dx_except
);
// TODO TODO factor this out in a cleaner way, e.g. separate out registers and stall logic.
`include "rv_opcodes.vh"
`include "hazard5_ops.vh"
// ============================================================================
localparam HAVE_CSR = CSR_M_MANDATORY || CSR_M_TRAP || CSR_COUNTER;
// ----------------------------------------------------------------------------
// Expand compressed instructions
wire [31:0] d_instr;
wire d_instr_is_32bit;
wire d_invalid_16bit;
reg d_invalid_32bit;
wire d_invalid = d_invalid_16bit || d_invalid_32bit;
hazard5_instr_decompress #(
.PASSTHROUGH(!EXTENSION_C)
) decomp (
.instr_in (fd_cir),
.instr_is_32bit (d_instr_is_32bit),
.instr_out (d_instr),
.invalid (d_invalid_16bit)
);
// Decode various immmediate formats
wire [31:0] d_imm_i = {{21{d_instr[31]}}, d_instr[30:20]};
wire [31:0] d_imm_s = {{21{d_instr[31]}}, d_instr[30:25], d_instr[11:7]};
wire [31:0] d_imm_b = {{20{d_instr[31]}}, d_instr[7], d_instr[30:25], d_instr[11:8], 1'b0};
wire [31:0] d_imm_u = {d_instr[31:12], {12{1'b0}}};
wire [31:0] d_imm_j = {{12{d_instr[31]}}, d_instr[19:12], d_instr[20], d_instr[30:21], 1'b0};
// ----------------------------------------------------------------------------
// PC/CIR control
// ============================================================================
wire d_starved = ~|fd_cir_vld || fd_cir_vld[0] && d_instr_is_32bit;
assign d_stall = x_stall ||
@ -131,7 +151,6 @@ always @ (posedge clk or negedge rst_n) begin
end
// If the current CIR is there due to locking, it is a jump which has already had primary effect.
wire d_invalid;
wire jump_enable = !d_starved && !cir_lock_prev && !d_invalid;
reg [W_ADDR-1:0] d_jump_offs;
@ -158,35 +177,8 @@ always @ (*) begin
endcase
end
// ============================================================================
// Expand compressed instructions
// ============================================================================
wire [31:0] d_instr;
wire d_instr_is_32bit;
wire d_invalid_16bit;
reg d_invalid_32bit;
assign d_invalid = d_invalid_16bit || d_invalid_32bit;
hazard5_instr_decompress #(
.PASSTHROUGH(!EXTENSION_C)
) decomp (
.instr_in (fd_cir),
.instr_is_32bit (d_instr_is_32bit),
.instr_out (d_instr),
.invalid (d_invalid_16bit)
);
// ============================================================================
// ----------------------------------------------------------------------------
// Decode X controls
// ============================================================================
// Decode various immmediate formats
wire [31:0] d_imm_i = {{21{d_instr[31]}}, d_instr[30:20]};
wire [31:0] d_imm_s = {{21{d_instr[31]}}, d_instr[30:25], d_instr[11:7]};
wire [31:0] d_imm_b = {{20{d_instr[31]}}, d_instr[7], d_instr[30:25], d_instr[11:8], 1'b0};
wire [31:0] d_imm_u = {d_instr[31:12], {12{1'b0}}};
wire [31:0] d_imm_j = {{12{d_instr[31]}}, d_instr[19:12], d_instr[20], d_instr[30:21], 1'b0};
// Combinatorials:
reg [W_REGADDR-1:0] d_rd;

View File

@ -1,9 +1,6 @@
module hazard5_frontend #(
parameter EXTENSION_C = 1,
parameter W_ADDR = 32, // other sizes currently unsupported
parameter W_DATA = 32, // other sizes currently unsupported
parameter FIFO_DEPTH = 2, // power of 2, >= 1
parameter RESET_VECTOR = 0
`include "hazard5_config.vh"
) (
input wire clk,
input wire rst_n,
@ -71,19 +68,31 @@ parameter W_FIFO_LEVEL = $clog2(FIFO_DEPTH + 1);
wire jump_now = jump_target_vld && jump_target_rdy;
reg [W_DATA-1:0] fifo_mem [0:FIFO_DEPTH];
reg [FIFO_DEPTH-1:0] fifo_valid;
// mem has an extra entry which is equal to next-but-last entry, and valid has
// an extra entry which is constant-0. These are just there to handle loop
// boundary conditions.
reg [W_DATA-1:0] fifo_mem [0:FIFO_DEPTH];
reg [FIFO_DEPTH:0] fifo_valid;
wire [W_DATA-1:0] fifo_wdata = mem_data;
wire [W_DATA-1:0] fifo_rdata = fifo_mem[0];
always @ (*) fifo_mem[FIFO_DEPTH] = fifo_wdata;
wire fifo_full = fifo_valid[FIFO_DEPTH - 1];
wire fifo_empty = !fifo_valid[0];
wire fifo_almost_full = FIFO_DEPTH == 1 || (!fifo_valid[FIFO_DEPTH - 1] && fifo_valid[FIFO_DEPTH - 2]);
wire fifo_push;
wire fifo_pop;
always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin
fifo_valid <= {FIFO_DEPTH{1'b0}};
fifo_valid <= {FIFO_DEPTH+1{1'b0}};
end else if (jump_now) begin
fifo_valid <= {FIFO_DEPTH{1'b0}};
fifo_valid[FIFO_DEPTH-1:0] <= {FIFO_DEPTH{1'b0}};
end else if (fifo_push || fifo_pop) begin
fifo_valid <= ~(~fifo_valid << fifo_push) >> fifo_pop;
fifo_valid[FIFO_DEPTH-1:0] <= ~(~fifo_valid << fifo_push) >> fifo_pop;
end
end
@ -96,14 +105,6 @@ always @ (posedge clk) begin: fifo_data_shift
end
end
wire [W_DATA-1:0] fifo_wdata = mem_data;
wire [W_DATA-1:0] fifo_rdata = fifo_mem[0];
always @ (*) fifo_mem[FIFO_DEPTH] = fifo_wdata;
wire fifo_full = fifo_valid[FIFO_DEPTH - 1];
wire fifo_empty = !fifo_valid[0];
wire fifo_almost_full = FIFO_DEPTH == 1 || (!fifo_valid[FIFO_DEPTH - 1] && fifo_valid[FIFO_DEPTH - 2]);
// ============================================================================
// Fetch Request + State Logic
// ============================================================================

View File

@ -1,9 +1,4 @@
localparam W_ALUOP = 4;
localparam W_ALUSRC = 2;
localparam W_MEMOP = 4;
localparam W_BCOND = 2;
// ALU operation selectors
localparam ALUOP_ADD = 4'h0;
@ -52,7 +47,6 @@ localparam CSR_WTYPE_C = 2'h2;
// instructions in the pipeline. These are speculative and can be flushed
// on e.g. branch mispredict
localparam W_EXCEPT = 3;
localparam EXCEPT_NONE = 3'h0;
localparam EXCEPT_ECALL = 3'h1;
localparam EXCEPT_EBREAK = 3'h2;
@ -63,7 +57,6 @@ localparam EXCEPT_INSTR_FAULT = 3'h6;
// Operations for M extension (these are just instr[14:12])
localparam W_MULOP = 3;
localparam M_OP_MUL = 3'h0;
localparam M_OP_MULH = 3'h1;
localparam M_OP_MULHSU = 3'h2;

View File

@ -0,0 +1,14 @@
// These really ought to be localparams, but are occasionally needed for
// passing flags around between modules, so are made available as parameters
// instead. It's ugly, but better scope hygiene than the preprocessor. These
// parameters should not be changed from their default values.
parameter W_REGADDR = 5,
parameter W_ALUOP = 4,
parameter W_ALUSRC = 2,
parameter W_MEMOP = 4,
parameter W_BCOND = 2,
parameter W_EXCEPT = 3,
parameter W_MULOP = 3