URL
https://opencores.org/ocsvn/altor32/altor32/trunk
Subversion Repositories altor32
Compare Revisions
- This comparison shows the changes necessary to convert path
/altor32/trunk
- from Rev 26 to Rev 27
- ↔ Reverse comparison
Rev 26 → Rev 27
/rtl/soc/dmem_mux3.v
0,0 → 1,199
|
//----------------------------------------------------------------- |
// Module: |
//----------------------------------------------------------------- |
module dmem_mux3 |
( |
// Outputs |
out0_addr_o, |
out0_data_o, |
out0_data_i, |
out0_wr_o, |
out0_rd_o, |
out0_burst_o, |
out0_ack_i, |
out0_accept_i, |
out1_addr_o, |
out1_data_o, |
out1_data_i, |
out1_wr_o, |
out1_rd_o, |
out1_burst_o, |
out1_ack_i, |
out1_accept_i, |
out2_addr_o, |
out2_data_o, |
out2_data_i, |
out2_wr_o, |
out2_rd_o, |
out2_burst_o, |
out2_ack_i, |
out2_accept_i, |
|
// Input |
mem_addr_i, |
mem_data_i, |
mem_data_o, |
mem_burst_i, |
mem_wr_i, |
mem_rd_i, |
mem_ack_o, |
mem_accept_o |
); |
|
//----------------------------------------------------------------- |
// Params |
//----------------------------------------------------------------- |
parameter ADDR_MUX_START = 28; |
|
//----------------------------------------------------------------- |
// I/O |
//----------------------------------------------------------------- |
input [31:0] mem_addr_i /*verilator public*/; |
input [31:0] mem_data_i /*verilator public*/; |
output [31:0] mem_data_o /*verilator public*/; |
input [3:0] mem_wr_i /*verilator public*/; |
input mem_rd_i /*verilator public*/; |
input mem_burst_i /*verilator public*/; |
output mem_ack_o /*verilator public*/; |
output mem_accept_o /*verilator public*/; |
output [31:0] out0_addr_o /*verilator public*/; |
output [31:0] out0_data_o /*verilator public*/; |
input [31:0] out0_data_i /*verilator public*/; |
output [3:0] out0_wr_o /*verilator public*/; |
output out0_rd_o /*verilator public*/; |
output out0_burst_o /*verilator public*/; |
input out0_ack_i /*verilator public*/; |
input out0_accept_i /*verilator public*/; |
output [31:0] out1_addr_o /*verilator public*/; |
output [31:0] out1_data_o /*verilator public*/; |
input [31:0] out1_data_i /*verilator public*/; |
output [3:0] out1_wr_o /*verilator public*/; |
output out1_rd_o /*verilator public*/; |
output out1_burst_o /*verilator public*/; |
input out1_ack_i /*verilator public*/; |
input out1_accept_i /*verilator public*/; |
output [31:0] out2_addr_o /*verilator public*/; |
output [31:0] out2_data_o /*verilator public*/; |
input [31:0] out2_data_i /*verilator public*/; |
output [3:0] out2_wr_o /*verilator public*/; |
output out2_rd_o /*verilator public*/; |
output out2_burst_o /*verilator public*/; |
input out2_ack_i /*verilator public*/; |
input out2_accept_i /*verilator public*/; |
|
//----------------------------------------------------------------- |
// Registers |
//----------------------------------------------------------------- |
|
// Output Signals |
reg mem_ack_o; |
reg mem_accept_o; |
reg [31:0] mem_data_o; |
|
reg [31:0] out0_addr_o; |
reg [31:0] out0_data_o; |
reg [3:0] out0_wr_o; |
reg out0_rd_o; |
reg out0_burst_o; |
reg [31:0] out1_addr_o; |
reg [31:0] out1_data_o; |
reg [3:0] out1_wr_o; |
reg out1_rd_o; |
reg out1_burst_o; |
reg [31:0] out2_addr_o; |
reg [31:0] out2_data_o; |
reg [3:0] out2_wr_o; |
reg out2_rd_o; |
reg out2_burst_o; |
|
//----------------------------------------------------------------- |
// Memory Map |
//----------------------------------------------------------------- |
always @ (mem_addr_i or mem_wr_i or mem_rd_i or mem_data_i or mem_burst_i) |
begin |
|
out0_addr_o = 32'h00000000; |
out0_wr_o = 4'b0000; |
out0_rd_o = 1'b0; |
out0_data_o = 32'h00000000; |
out0_burst_o = 1'b0; |
out1_addr_o = 32'h00000000; |
out1_wr_o = 4'b0000; |
out1_rd_o = 1'b0; |
out1_data_o = 32'h00000000; |
out1_burst_o = 1'b0; |
out2_addr_o = 32'h00000000; |
out2_wr_o = 4'b0000; |
out2_rd_o = 1'b0; |
out2_data_o = 32'h00000000; |
out2_burst_o = 1'b0; |
|
case (mem_addr_i[ADDR_MUX_START+2-1:ADDR_MUX_START]) |
|
2'd0: |
begin |
out0_addr_o = mem_addr_i; |
out0_wr_o = mem_wr_i; |
out0_rd_o = mem_rd_i; |
out0_data_o = mem_data_i; |
out0_burst_o = mem_burst_i; |
end |
2'd1: |
begin |
out1_addr_o = mem_addr_i; |
out1_wr_o = mem_wr_i; |
out1_rd_o = mem_rd_i; |
out1_data_o = mem_data_i; |
out1_burst_o = mem_burst_i; |
end |
2'd2: |
begin |
out2_addr_o = mem_addr_i; |
out2_wr_o = mem_wr_i; |
out2_rd_o = mem_rd_i; |
out2_data_o = mem_data_i; |
out2_burst_o = mem_burst_i; |
end |
|
default : |
; |
endcase |
end |
|
//----------------------------------------------------------------- |
// Read Port |
//----------------------------------------------------------------- |
always @ * |
begin |
case (mem_addr_i[ADDR_MUX_START+2-1:ADDR_MUX_START]) |
|
2'd0: |
begin |
mem_data_o = out0_data_i; |
mem_accept_o = out0_accept_i; |
mem_ack_o = out0_ack_i; |
end |
2'd1: |
begin |
mem_data_o = out1_data_i; |
mem_accept_o = out1_accept_i; |
mem_ack_o = out1_ack_i; |
end |
2'd2: |
begin |
mem_data_o = out2_data_i; |
mem_accept_o = out2_accept_i; |
mem_ack_o = out2_ack_i; |
end |
|
default : |
begin |
mem_data_o = 32'h00000000; |
mem_accept_o = 1'b0; |
mem_ack_o = 1'b0; |
end |
endcase |
end |
|
endmodule |
/rtl/soc/soc.v
0,0 → 1,266
|
//----------------------------------------------------------------- |
// Module: |
//----------------------------------------------------------------- |
module soc |
( |
// General - Clocking & Reset |
clk_i, |
rst_i, |
ext_intr_i, |
intr_o, |
|
|
|
|
|
|
|
|
|
// Memory interface |
io_addr_i, |
io_data_i, |
io_data_o, |
io_wr_i, |
io_rd_i |
); |
|
//----------------------------------------------------------------- |
// Params |
//----------------------------------------------------------------- |
parameter [31:0] CLK_KHZ = 12288; |
parameter [31:0] UART_BAUD = 115200; |
parameter [31:0] SPI_FLASH_CLK_KHZ = (12288/2); |
parameter SD_CLK_KHZ = 8000; |
parameter [31:0] EXTERNAL_INTERRUPTS = 1; |
parameter SYSTICK_INTR_MS = 1; |
parameter ENABLE_SYSTICK_TIMER = "ENABLED"; |
parameter ENABLE_HIGHRES_TIMER = "ENABLED"; |
|
//----------------------------------------------------------------- |
// I/O |
//----------------------------------------------------------------- |
input clk_i /*verilator public*/; |
input rst_i /*verilator public*/; |
input [(EXTERNAL_INTERRUPTS - 1):0] ext_intr_i /*verilator public*/; |
output intr_o /*verilator public*/; |
|
|
// Memory Port |
input [31:0] io_addr_i /*verilator public*/; |
input [31:0] io_data_i /*verilator public*/; |
output [31:0] io_data_o /*verilator public*/; |
input [3:0] io_wr_i /*verilator public*/; |
input io_rd_i /*verilator public*/; |
|
|
|
|
|
|
|
|
//----------------------------------------------------------------- |
// Registers / Wires |
//----------------------------------------------------------------- |
|
|
|
|
|
|
|
|
wire [7:0] timer_addr; |
wire [31:0] timer_data_o; |
wire [31:0] timer_data_i; |
wire [3:0] timer_wr; |
wire timer_rd; |
wire timer_intr_systick; |
wire timer_intr_hires; |
|
wire [7:0] intr_addr; |
wire [31:0] intr_data_o; |
wire [31:0] intr_data_i; |
wire [3:0] intr_wr; |
wire intr_rd; |
|
//----------------------------------------------------------------- |
// Peripheral Interconnect |
//----------------------------------------------------------------- |
soc_pif8 |
u2_soc |
( |
// General - Clocking & Reset |
.clk_i(clk_i), |
.rst_i(rst_i), |
|
// I/O bus (from mem_mux) |
// 0x12000000 - 0x12FFFFFF |
.io_addr_i(io_addr_i), |
.io_data_i(io_data_i), |
.io_data_o(io_data_o), |
.io_wr_i(io_wr_i), |
.io_rd_i(io_rd_i), |
|
// Peripherals |
// Unused = 0x12000000 - 0x120000FF |
.periph0_addr_o(/*open*/), |
.periph0_data_o(/*open*/), |
.periph0_data_i(32'h00000000), |
.periph0_wr_o(/*open*/), |
.periph0_rd_o(/*open*/), |
|
// Timer = 0x12000100 - 0x120001FF |
.periph1_addr_o(timer_addr), |
.periph1_data_o(timer_data_o), |
.periph1_data_i(timer_data_i), |
.periph1_wr_o(timer_wr), |
.periph1_rd_o(timer_rd), |
|
// Interrupt Controller = 0x12000200 - 0x120002FF |
.periph2_addr_o(intr_addr), |
.periph2_data_o(intr_data_o), |
.periph2_data_i(intr_data_i), |
.periph2_wr_o(intr_wr), |
.periph2_rd_o(intr_rd), |
|
// Unused = 0x12000300 - 0x120003FF |
.periph3_addr_o(/*open*/), |
.periph3_data_o(/*open*/), |
.periph3_data_i(32'h00000000), |
.periph3_wr_o(/*open*/), |
.periph3_rd_o(/*open*/), |
|
// Unused = 0x12000400 - 0x120004FF |
.periph4_addr_o(/*open*/), |
.periph4_data_o(/*open*/), |
.periph4_data_i(32'h00000000), |
.periph4_wr_o(/*open*/), |
.periph4_rd_o(/*open*/), |
|
// Unused = 0x12000500 - 0x120005FF |
.periph5_addr_o(/*open*/), |
.periph5_data_o(/*open*/), |
.periph5_data_i(32'h00000000), |
.periph5_wr_o(/*open*/), |
.periph5_rd_o(/*open*/), |
|
// Unused = 0x12000600 - 0x120006FF |
.periph6_addr_o(/*open*/), |
.periph6_data_o(/*open*/), |
.periph6_data_i(32'h00000000), |
.periph6_wr_o(/*open*/), |
.periph6_rd_o(/*open*/), |
|
// Unused = 0x12000700 - 0x120007FF |
.periph7_addr_o(/*open*/), |
.periph7_data_o(/*open*/), |
.periph7_data_i(32'h00000000), |
.periph7_wr_o(/*open*/), |
.periph7_rd_o(/*open*/) |
); |
|
//----------------------------------------------------------------- |
// Memory master arbiter |
//----------------------------------------------------------------- |
|
//----------------------------------------------------------------- |
// UART |
//----------------------------------------------------------------- |
|
//----------------------------------------------------------------- |
// GPIO |
//----------------------------------------------------------------- |
|
//----------------------------------------------------------------- |
// SPI Flash Master |
//----------------------------------------------------------------- |
|
//----------------------------------------------------------------- |
// DMA |
//----------------------------------------------------------------- |
|
//----------------------------------------------------------------- |
// SD |
//----------------------------------------------------------------- |
|
//----------------------------------------------------------------- |
// Generic Register |
//----------------------------------------------------------------- |
|
//----------------------------------------------------------------- |
// Timer |
//----------------------------------------------------------------- |
timer_periph |
#( |
.CLK_KHZ(CLK_KHZ), |
.SYSTICK_INTR_MS(SYSTICK_INTR_MS), |
.ENABLE_SYSTICK_TIMER(ENABLE_SYSTICK_TIMER), |
.ENABLE_HIGHRES_TIMER(ENABLE_HIGHRES_TIMER) |
) |
u5_timer |
( |
.clk_i(clk_i), |
.rst_i(rst_i), |
.intr_systick_o(timer_intr_systick), |
.intr_hires_o(timer_intr_hires), |
.addr_i(timer_addr), |
.data_o(timer_data_i), |
.data_i(timer_data_o), |
.wr_i(timer_wr), |
.rd_i(timer_rd) |
); |
|
//----------------------------------------------------------------- |
// Interrupt Controller |
//----------------------------------------------------------------- |
intr_periph |
#( |
.EXTERNAL_INTERRUPTS(EXTERNAL_INTERRUPTS) |
) |
u6_intr |
( |
.clk_i(clk_i), |
.rst_i(rst_i), |
.intr_o(intr_o), |
|
.intr0_i(1'b0), |
|
.intr1_i(timer_intr_systick), |
.intr2_i(timer_intr_hires), |
.intr3_i(1'b0), |
|
.intr4_i(1'b0), |
|
.intr5_i(1'b0), |
|
.intr6_i(1'b0), |
|
.intr7_i(1'b0), |
.intr_ext_i(ext_intr_i), |
|
.addr_i(intr_addr), |
.data_o(intr_data_i), |
.data_i(intr_data_o), |
.wr_i(intr_wr), |
.rd_i(intr_rd) |
); |
|
//------------------------------------------------------------------- |
// Hooks for debug |
//------------------------------------------------------------------- |
`ifdef verilator |
function [0:0] get_uart_wr; |
// verilator public |
get_uart_wr = 1'b0; |
endfunction |
|
function [7:0] get_uart_data; |
// verilator public |
get_uart_data = 8'b0; |
endfunction |
`endif |
|
endmodule |
/rtl/soc/cpu_if.v
0,0 → 1,232
|
//----------------------------------------------------------------- |
// Module: |
//----------------------------------------------------------------- |
module cpu_if |
( |
// General - Clocking & Reset |
clk_i, |
rst_i, |
|
// Instruction Memory 0 (0x10000000 - 0x10FFFFFF) |
imem0_addr_o, |
imem0_rd_o, |
imem0_burst_o, |
imem0_data_in_i, |
imem0_accept_i, |
imem0_ack_i, |
|
// Data Memory 0 (0x10000000 - 0x10FFFFFF) |
dmem0_addr_o, |
dmem0_data_o, |
dmem0_data_i, |
dmem0_wr_o, |
dmem0_rd_o, |
dmem0_burst_o, |
dmem0_accept_i, |
dmem0_ack_i, |
// Data Memory 1 (0x11000000 - 0x11FFFFFF) |
dmem1_addr_o, |
dmem1_data_o, |
dmem1_data_i, |
dmem1_wr_o, |
dmem1_rd_o, |
dmem1_burst_o, |
dmem1_accept_i, |
dmem1_ack_i, |
// Data Memory 2 (0x12000000 - 0x12FFFFFF) |
dmem2_addr_o, |
dmem2_data_o, |
dmem2_data_i, |
dmem2_wr_o, |
dmem2_rd_o, |
dmem2_burst_o, |
dmem2_accept_i, |
dmem2_ack_i, |
|
fault_o, |
break_o, |
intr_i, |
nmi_i |
); |
|
//----------------------------------------------------------------- |
// Params |
//----------------------------------------------------------------- |
parameter [31:0] CLK_KHZ = 12288; |
parameter ENABLE_ICACHE = "ENABLED"; |
parameter ENABLE_DCACHE = "DISABLED"; |
parameter BOOT_VECTOR = 0; |
parameter ISR_VECTOR = 0; |
parameter REGISTER_FILE_TYPE = "SIMULATION"; |
|
//----------------------------------------------------------------- |
// I/O |
//----------------------------------------------------------------- |
input clk_i /*verilator public*/; |
input rst_i /*verilator public*/; |
|
// Instruction Memory 0 (0x10000000 - 0x10FFFFFF) |
output [31:0] imem0_addr_o /*verilator public*/; |
output imem0_rd_o /*verilator public*/; |
output imem0_burst_o /*verilator public*/; |
input [31:0] imem0_data_in_i /*verilator public*/; |
input imem0_accept_i /*verilator public*/; |
input imem0_ack_i /*verilator public*/; |
|
// Data Memory 0 (0x10000000 - 0x10FFFFFF) |
output [31:0] dmem0_addr_o /*verilator public*/; |
output [31:0] dmem0_data_o /*verilator public*/; |
input [31:0] dmem0_data_i /*verilator public*/; |
output [3:0] dmem0_wr_o /*verilator public*/; |
output dmem0_rd_o /*verilator public*/; |
output dmem0_burst_o /*verilator public*/; |
input dmem0_accept_i /*verilator public*/; |
input dmem0_ack_i /*verilator public*/; |
// Data Memory 1 (0x11000000 - 0x11FFFFFF) |
output [31:0] dmem1_addr_o /*verilator public*/; |
output [31:0] dmem1_data_o /*verilator public*/; |
input [31:0] dmem1_data_i /*verilator public*/; |
output [3:0] dmem1_wr_o /*verilator public*/; |
output dmem1_rd_o /*verilator public*/; |
output dmem1_burst_o /*verilator public*/; |
input dmem1_accept_i /*verilator public*/; |
input dmem1_ack_i /*verilator public*/; |
// Data Memory 2 (0x12000000 - 0x12FFFFFF) |
output [31:0] dmem2_addr_o /*verilator public*/; |
output [31:0] dmem2_data_o /*verilator public*/; |
input [31:0] dmem2_data_i /*verilator public*/; |
output [3:0] dmem2_wr_o /*verilator public*/; |
output dmem2_rd_o /*verilator public*/; |
output dmem2_burst_o /*verilator public*/; |
input dmem2_accept_i /*verilator public*/; |
input dmem2_ack_i /*verilator public*/; |
|
output fault_o /*verilator public*/; |
output break_o /*verilator public*/; |
input nmi_i /*verilator public*/; |
input intr_i /*verilator public*/; |
|
//----------------------------------------------------------------- |
// Registers |
//----------------------------------------------------------------- |
wire [31:0] cpu_address; |
wire [3:0] cpu_wr; |
wire cpu_rd; |
wire cpu_burst; |
wire [31:0] cpu_data_w; |
wire [31:0] cpu_data_r; |
wire cpu_accept; |
wire cpu_ack; |
|
wire [31:0] imem_address; |
wire [31:0] imem_data; |
wire imem_rd; |
wire imem_burst; |
wire imem_ack; |
wire imem_accept; |
|
//----------------------------------------------------------------- |
// CPU core |
//----------------------------------------------------------------- |
cpu |
#( |
.BOOT_VECTOR(BOOT_VECTOR), |
.ISR_VECTOR(ISR_VECTOR), |
.REGISTER_FILE_TYPE(REGISTER_FILE_TYPE), |
.ENABLE_ICACHE(ENABLE_ICACHE), |
.ENABLE_DCACHE(ENABLE_DCACHE) |
) |
u1_cpu |
( |
.clk_i(clk_i), |
.rst_i(rst_i), |
|
.intr_i(intr_i), |
.nmi_i(nmi_i), |
|
// Status |
.fault_o(fault_o), |
.break_o(break_o), |
|
// Instruction memory |
.imem_addr_o(imem_address), |
.imem_rd_o(imem_rd), |
.imem_burst_o(imem_burst), |
.imem_data_in_i(imem_data), |
.imem_accept_i(imem_accept), |
.imem_ack_i(imem_ack), |
|
// Data memory |
.dmem_addr_o(cpu_address), |
.dmem_data_out_o(cpu_data_w), |
.dmem_data_in_i(cpu_data_r), |
.dmem_wr_o(cpu_wr), |
.dmem_rd_o(cpu_rd), |
.dmem_burst_o(cpu_burst), |
.dmem_accept_i(cpu_accept), |
.dmem_ack_i(cpu_ack) |
); |
|
//----------------------------------------------------------------- |
// Instruction Memory MUX |
//----------------------------------------------------------------- |
|
assign imem0_addr_o = imem_address; |
assign imem0_rd_o = imem_rd; |
assign imem0_burst_o = imem_burst; |
assign imem_data = imem0_data_in_i; |
assign imem_accept = imem0_accept_i; |
assign imem_ack = imem0_ack_i; |
|
|
//----------------------------------------------------------------- |
// Data Memory MUX |
//----------------------------------------------------------------- |
dmem_mux3 |
#( |
.ADDR_MUX_START(24) |
) |
u_dmux |
( |
// Outputs |
// 0x10000000 - 0x10FFFFFF |
.out0_addr_o(dmem0_addr_o), |
.out0_data_o(dmem0_data_o), |
.out0_data_i(dmem0_data_i), |
.out0_wr_o(dmem0_wr_o), |
.out0_rd_o(dmem0_rd_o), |
.out0_burst_o(dmem0_burst_o), |
.out0_ack_i(dmem0_ack_i), |
.out0_accept_i(dmem0_accept_i), |
// 0x11000000 - 0x11FFFFFF |
.out1_addr_o(dmem1_addr_o), |
.out1_data_o(dmem1_data_o), |
.out1_data_i(dmem1_data_i), |
.out1_wr_o(dmem1_wr_o), |
.out1_rd_o(dmem1_rd_o), |
.out1_burst_o(dmem1_burst_o), |
.out1_ack_i(dmem1_ack_i), |
.out1_accept_i(dmem1_accept_i), |
// 0x12000000 - 0x12FFFFFF |
.out2_addr_o(dmem2_addr_o), |
.out2_data_o(dmem2_data_o), |
.out2_data_i(dmem2_data_i), |
.out2_wr_o(dmem2_wr_o), |
.out2_rd_o(dmem2_rd_o), |
.out2_burst_o(dmem2_burst_o), |
.out2_ack_i(dmem2_ack_i), |
.out2_accept_i(dmem2_accept_i), |
|
// Input - CPU core bus |
.mem_addr_i(cpu_address), |
.mem_data_i(cpu_data_w), |
.mem_data_o(cpu_data_r), |
.mem_wr_i(cpu_wr), |
.mem_rd_i(cpu_rd), |
.mem_burst_i(cpu_burst), |
.mem_ack_o(cpu_ack), |
.mem_accept_o(cpu_accept) |
); |
|
endmodule |
/rtl/soc/soc_pif8.v
0,0 → 1,332
|
//----------------------------------------------------------------- |
// Module: |
//----------------------------------------------------------------- |
module soc_pif8 |
( |
// General - Clocking & Reset |
clk_i, |
rst_i, |
|
// Peripherals |
periph0_addr_o, |
periph0_data_o, |
periph0_data_i, |
periph0_wr_o, |
periph0_rd_o, |
periph1_addr_o, |
periph1_data_o, |
periph1_data_i, |
periph1_wr_o, |
periph1_rd_o, |
periph2_addr_o, |
periph2_data_o, |
periph2_data_i, |
periph2_wr_o, |
periph2_rd_o, |
periph3_addr_o, |
periph3_data_o, |
periph3_data_i, |
periph3_wr_o, |
periph3_rd_o, |
periph4_addr_o, |
periph4_data_o, |
periph4_data_i, |
periph4_wr_o, |
periph4_rd_o, |
periph5_addr_o, |
periph5_data_o, |
periph5_data_i, |
periph5_wr_o, |
periph5_rd_o, |
periph6_addr_o, |
periph6_data_o, |
periph6_data_i, |
periph6_wr_o, |
periph6_rd_o, |
periph7_addr_o, |
periph7_data_o, |
periph7_data_i, |
periph7_wr_o, |
periph7_rd_o, |
|
// I/O bus |
io_addr_i, |
io_data_i, |
io_data_o, |
io_wr_i, |
io_rd_i |
); |
|
//----------------------------------------------------------------- |
// I/O |
//----------------------------------------------------------------- |
input clk_i /*verilator public*/; |
input rst_i /*verilator public*/; |
|
input [31:0] io_addr_i /*verilator public*/; |
output [31:0] io_data_o /*verilator public*/; |
input [31:0] io_data_i /*verilator public*/; |
input [3:0] io_wr_i /*verilator public*/; |
input io_rd_i /*verilator public*/; |
|
output [7:0] periph0_addr_o /*verilator public*/; |
output [31:0] periph0_data_o /*verilator public*/; |
input [31:0] periph0_data_i /*verilator public*/; |
output [3:0] periph0_wr_o /*verilator public*/; |
output periph0_rd_o /*verilator public*/; |
output [7:0] periph1_addr_o /*verilator public*/; |
output [31:0] periph1_data_o /*verilator public*/; |
input [31:0] periph1_data_i /*verilator public*/; |
output [3:0] periph1_wr_o /*verilator public*/; |
output periph1_rd_o /*verilator public*/; |
output [7:0] periph2_addr_o /*verilator public*/; |
output [31:0] periph2_data_o /*verilator public*/; |
input [31:0] periph2_data_i /*verilator public*/; |
output [3:0] periph2_wr_o /*verilator public*/; |
output periph2_rd_o /*verilator public*/; |
output [7:0] periph3_addr_o /*verilator public*/; |
output [31:0] periph3_data_o /*verilator public*/; |
input [31:0] periph3_data_i /*verilator public*/; |
output [3:0] periph3_wr_o /*verilator public*/; |
output periph3_rd_o /*verilator public*/; |
output [7:0] periph4_addr_o /*verilator public*/; |
output [31:0] periph4_data_o /*verilator public*/; |
input [31:0] periph4_data_i /*verilator public*/; |
output [3:0] periph4_wr_o /*verilator public*/; |
output periph4_rd_o /*verilator public*/; |
output [7:0] periph5_addr_o /*verilator public*/; |
output [31:0] periph5_data_o /*verilator public*/; |
input [31:0] periph5_data_i /*verilator public*/; |
output [3:0] periph5_wr_o /*verilator public*/; |
output periph5_rd_o /*verilator public*/; |
output [7:0] periph6_addr_o /*verilator public*/; |
output [31:0] periph6_data_o /*verilator public*/; |
input [31:0] periph6_data_i /*verilator public*/; |
output [3:0] periph6_wr_o /*verilator public*/; |
output periph6_rd_o /*verilator public*/; |
output [7:0] periph7_addr_o /*verilator public*/; |
output [31:0] periph7_data_o /*verilator public*/; |
input [31:0] periph7_data_i /*verilator public*/; |
output [3:0] periph7_wr_o /*verilator public*/; |
output periph7_rd_o /*verilator public*/; |
|
//----------------------------------------------------------------- |
// Registers |
//----------------------------------------------------------------- |
reg [3:0] r_mem_sel; |
|
reg [31:0] io_data_o; |
|
reg [7:0] periph0_addr_o; |
reg [31:0] periph0_data_o; |
reg [3:0] periph0_wr_o; |
reg periph0_rd_o; |
reg [7:0] periph1_addr_o; |
reg [31:0] periph1_data_o; |
reg [3:0] periph1_wr_o; |
reg periph1_rd_o; |
reg [7:0] periph2_addr_o; |
reg [31:0] periph2_data_o; |
reg [3:0] periph2_wr_o; |
reg periph2_rd_o; |
reg [7:0] periph3_addr_o; |
reg [31:0] periph3_data_o; |
reg [3:0] periph3_wr_o; |
reg periph3_rd_o; |
reg [7:0] periph4_addr_o; |
reg [31:0] periph4_data_o; |
reg [3:0] periph4_wr_o; |
reg periph4_rd_o; |
reg [7:0] periph5_addr_o; |
reg [31:0] periph5_data_o; |
reg [3:0] periph5_wr_o; |
reg periph5_rd_o; |
reg [7:0] periph6_addr_o; |
reg [31:0] periph6_data_o; |
reg [3:0] periph6_wr_o; |
reg periph6_rd_o; |
reg [7:0] periph7_addr_o; |
reg [31:0] periph7_data_o; |
reg [3:0] periph7_wr_o; |
reg periph7_rd_o; |
|
//----------------------------------------------------------------- |
// Memory Map |
//----------------------------------------------------------------- |
always @ (io_addr_i or io_wr_i or io_rd_i or io_data_i) |
begin |
|
periph0_addr_o = 8'h00; |
periph0_wr_o = 4'b0000; |
periph0_rd_o = 1'b0; |
periph0_data_o = 32'h00000000; |
periph1_addr_o = 8'h00; |
periph1_wr_o = 4'b0000; |
periph1_rd_o = 1'b0; |
periph1_data_o = 32'h00000000; |
periph2_addr_o = 8'h00; |
periph2_wr_o = 4'b0000; |
periph2_rd_o = 1'b0; |
periph2_data_o = 32'h00000000; |
periph3_addr_o = 8'h00; |
periph3_wr_o = 4'b0000; |
periph3_rd_o = 1'b0; |
periph3_data_o = 32'h00000000; |
periph4_addr_o = 8'h00; |
periph4_wr_o = 4'b0000; |
periph4_rd_o = 1'b0; |
periph4_data_o = 32'h00000000; |
periph5_addr_o = 8'h00; |
periph5_wr_o = 4'b0000; |
periph5_rd_o = 1'b0; |
periph5_data_o = 32'h00000000; |
periph6_addr_o = 8'h00; |
periph6_wr_o = 4'b0000; |
periph6_rd_o = 1'b0; |
periph6_data_o = 32'h00000000; |
periph7_addr_o = 8'h00; |
periph7_wr_o = 4'b0000; |
periph7_rd_o = 1'b0; |
periph7_data_o = 32'h00000000; |
|
// Decode 4-bit peripheral select |
case (io_addr_i[11:8]) |
|
// Peripheral 0 |
4'd 0 : |
begin |
periph0_addr_o = io_addr_i[7:0]; |
periph0_wr_o = io_wr_i; |
periph0_rd_o = io_rd_i; |
periph0_data_o = io_data_i; |
end |
// Peripheral 1 |
4'd 1 : |
begin |
periph1_addr_o = io_addr_i[7:0]; |
periph1_wr_o = io_wr_i; |
periph1_rd_o = io_rd_i; |
periph1_data_o = io_data_i; |
end |
// Peripheral 2 |
4'd 2 : |
begin |
periph2_addr_o = io_addr_i[7:0]; |
periph2_wr_o = io_wr_i; |
periph2_rd_o = io_rd_i; |
periph2_data_o = io_data_i; |
end |
// Peripheral 3 |
4'd 3 : |
begin |
periph3_addr_o = io_addr_i[7:0]; |
periph3_wr_o = io_wr_i; |
periph3_rd_o = io_rd_i; |
periph3_data_o = io_data_i; |
end |
// Peripheral 4 |
4'd 4 : |
begin |
periph4_addr_o = io_addr_i[7:0]; |
periph4_wr_o = io_wr_i; |
periph4_rd_o = io_rd_i; |
periph4_data_o = io_data_i; |
end |
// Peripheral 5 |
4'd 5 : |
begin |
periph5_addr_o = io_addr_i[7:0]; |
periph5_wr_o = io_wr_i; |
periph5_rd_o = io_rd_i; |
periph5_data_o = io_data_i; |
end |
// Peripheral 6 |
4'd 6 : |
begin |
periph6_addr_o = io_addr_i[7:0]; |
periph6_wr_o = io_wr_i; |
periph6_rd_o = io_rd_i; |
periph6_data_o = io_data_i; |
end |
// Peripheral 7 |
4'd 7 : |
begin |
periph7_addr_o = io_addr_i[7:0]; |
periph7_wr_o = io_wr_i; |
periph7_rd_o = io_rd_i; |
periph7_data_o = io_data_i; |
end |
|
default : |
; |
endcase |
end |
|
//----------------------------------------------------------------- |
// Read Port |
//----------------------------------------------------------------- |
always @ * |
begin |
case (r_mem_sel) |
|
// Peripheral 0 |
4'd 0 : |
begin |
io_data_o = periph0_data_i; |
end |
// Peripheral 1 |
4'd 1 : |
begin |
io_data_o = periph1_data_i; |
end |
// Peripheral 2 |
4'd 2 : |
begin |
io_data_o = periph2_data_i; |
end |
// Peripheral 3 |
4'd 3 : |
begin |
io_data_o = periph3_data_i; |
end |
// Peripheral 4 |
4'd 4 : |
begin |
io_data_o = periph4_data_i; |
end |
// Peripheral 5 |
4'd 5 : |
begin |
io_data_o = periph5_data_i; |
end |
// Peripheral 6 |
4'd 6 : |
begin |
io_data_o = periph6_data_i; |
end |
// Peripheral 7 |
4'd 7 : |
begin |
io_data_o = periph7_data_i; |
end |
|
default : |
begin |
io_data_o = 32'h00000000; |
end |
endcase |
end |
|
//----------------------------------------------------------------- |
// Registered peripheral select |
//----------------------------------------------------------------- |
always @ (posedge clk_i or posedge rst_i) |
begin |
if (rst_i == 1'b1) |
r_mem_sel <= 4'h0; |
else |
r_mem_sel <= io_addr_i[11:8]; |
end |
|
endmodule |
/rtl/cpu/altor32_dcache.v
0,0 → 1,684
//----------------------------------------------------------------- |
// AltOR32 |
// Alternative Lightweight OpenRisc |
// V2.0 |
// Ultra-Embedded.com |
// Copyright 2011 - 2013 |
// |
// Email: admin@ultra-embedded.com |
// |
// License: LGPL |
//----------------------------------------------------------------- |
// |
// Copyright (C) 2011 - 2013 Ultra-Embedded.com |
// |
// This source file may be used and distributed without |
// restriction provided that this copyright statement is not |
// removed from the file and that any derivative work contains |
// the original copyright notice and the associated disclaimer. |
// |
// This source file is free software; you can redistribute it |
// and/or modify it under the terms of the GNU Lesser General |
// Public License as published by the Free Software Foundation; |
// either version 2.1 of the License, or (at your option) any |
// later version. |
// |
// This source is distributed in the hope that it will be |
// useful, but WITHOUT ANY WARRANTY; without even the implied |
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR |
// PURPOSE. See the GNU Lesser General Public License for more |
// details. |
// |
// You should have received a copy of the GNU Lesser General |
// Public License along with this source; if not, write to the |
// Free Software Foundation, Inc., 59 Temple Place, Suite 330, |
// Boston, MA 02111-1307 USA |
//----------------------------------------------------------------- |
|
//----------------------------------------------------------------- |
// Module - Data Cache (write back) |
//----------------------------------------------------------------- |
module altor32_dcache |
( |
input clk_i /*verilator public*/, |
input rst_i /*verilator public*/, |
|
input flush_i /*verilator public*/, |
|
// Input (CPU) |
input [31:0] address_i /*verilator public*/, |
output [31:0] data_o /*verilator public*/, |
input [31:0] data_i /*verilator public*/, |
input rd_i /*verilator public*/, |
input [3:0] wr_i /*verilator public*/, |
output accept_o /*verilator public*/, |
output ack_o /*verilator public*/, |
|
// Output (Memory) |
output [31:0] mem_addr_o /*verilator public*/, |
input [31:0] mem_data_i /*verilator public*/, |
output [31:0] mem_data_o /*verilator public*/, |
output mem_burst_o /*verilator public*/, |
output mem_rd_o /*verilator public*/, |
output [3:0] mem_wr_o /*verilator public*/, |
input mem_accept_i/*verilator public*/, |
input mem_ack_i/*verilator public*/ |
); |
|
//----------------------------------------------------------------- |
// Params |
//----------------------------------------------------------------- |
parameter CACHE_LINE_SIZE_WIDTH = 5; /* 5-bits -> 32 entries */ |
parameter CACHE_LINE_SIZE_BYTES = 2 ** CACHE_LINE_SIZE_WIDTH; /* 32 bytes / 8 words per line */ |
parameter CACHE_LINE_ADDR_WIDTH = 8; /* 256 lines */ |
parameter CACHE_LINE_WORDS_IDX_MAX = CACHE_LINE_SIZE_WIDTH - 2; /* 3-bit = 8 words */ |
parameter CACHE_TAG_ENTRIES = 2 ** CACHE_LINE_ADDR_WIDTH ; /* 256 tag entries */ |
parameter CACHE_DSIZE = CACHE_LINE_ADDR_WIDTH * CACHE_LINE_SIZE_BYTES; /* 8KB data */ |
parameter CACHE_DWIDTH = CACHE_LINE_ADDR_WIDTH + CACHE_LINE_SIZE_WIDTH - 2; /* 11-bits */ |
|
parameter CACHE_TAG_WIDTH = 16; /* 16-bit tag entry size */ |
parameter CACHE_TAG_LINE_ADDR_WIDTH = CACHE_TAG_WIDTH - 2; /* 14 bits of data (tag entry size minus valid/dirty bit) */ |
|
parameter CACHE_TAG_ADDR_LOW = CACHE_LINE_SIZE_WIDTH + CACHE_LINE_ADDR_WIDTH; |
parameter CACHE_TAG_ADDR_HIGH = CACHE_TAG_LINE_ADDR_WIDTH + CACHE_LINE_SIZE_WIDTH + CACHE_LINE_ADDR_WIDTH - 1; |
|
// Tag fields |
parameter CACHE_TAG_DIRTY_BIT = 14; |
parameter CACHE_TAG_VALID_BIT = 15; |
parameter ADDR_NO_CACHE_BIT = 25; |
parameter ADDR_CACHE_BYPASS_BIT = 31; |
|
// 31 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00 |
// |--------------| | | | | | | | | | | | | | | | | |
// +--------------------+ +-------------------+ +-----------+ |
// Tag entry Line address Address |
// (15-bits) (8-bits) within line |
// (5-bits) |
|
//----------------------------------------------------------------- |
// Registers / Wires |
//----------------------------------------------------------------- |
wire [CACHE_LINE_ADDR_WIDTH-1:0] tag_entry; |
wire [CACHE_TAG_WIDTH-1:0] tag_data_out; |
reg [CACHE_TAG_WIDTH-1:0] tag_data_in; |
reg tag_wr; |
|
wire [CACHE_DWIDTH-1:0] cache_address; |
wire [31:0] cache_data_r; |
reg [31:0] cache_data_w; |
reg [3:0] cache_wr; |
|
wire [31:2] cache_update_addr; |
wire [31:0] cache_update_data_w; |
wire [31:0] cache_update_data_r; |
wire cache_update_wr; |
|
reg ack; |
|
reg fill; |
reg evict; |
wire done; |
|
reg [31:0] data_w; |
wire [31:0] data_r; |
reg data_rd; |
reg [3:0] data_wr; |
|
reg req_rd; |
reg [3:0] req_wr; |
reg req_ack; |
reg [31:0] req_address; |
|
reg req_flush; |
reg flush_single; |
|
wire [31:0] line_address; |
|
wire [31:0] muxed_address = (state == STATE_IDLE) ? address_i : req_address; |
|
// Current state |
parameter STATE_IDLE = 0; |
parameter STATE_SINGLE = 1; |
parameter STATE_CHECK = 2; |
parameter STATE_FETCH = 3; |
parameter STATE_WAIT = 4; |
parameter STATE_WAIT2 = 5; |
parameter STATE_WRITE = 6; |
parameter STATE_SINGLE_READY= 7; |
parameter STATE_EVICTING = 8; |
parameter STATE_UPDATE = 9; |
parameter STATE_FLUSH1 = 10; |
parameter STATE_FLUSH2 = 11; |
parameter STATE_FLUSH3 = 12; |
parameter STATE_FLUSH4 = 13; |
reg [3:0] state; |
|
assign tag_entry = muxed_address[CACHE_LINE_ADDR_WIDTH + CACHE_LINE_SIZE_WIDTH - 1:CACHE_LINE_SIZE_WIDTH]; |
assign cache_address = {tag_entry, muxed_address[CACHE_LINE_SIZE_WIDTH-1:2]}; |
|
assign data_o = (state == STATE_SINGLE_READY) ? data_r : cache_data_r; |
assign accept_o = (state == STATE_IDLE); |
|
|
wire valid = tag_data_out[CACHE_TAG_VALID_BIT]; |
wire dirty = tag_data_out[CACHE_TAG_DIRTY_BIT]; |
|
// Access is cacheable? |
wire cacheable = ~muxed_address[ADDR_NO_CACHE_BIT] & ~muxed_address[ADDR_CACHE_BYPASS_BIT]; |
|
// Cache hit? |
wire hit = cacheable & valid & (muxed_address[CACHE_TAG_ADDR_HIGH:CACHE_TAG_ADDR_LOW] == tag_data_out[13:0]) & (state == STATE_CHECK); |
|
assign ack_o = ack | hit; |
|
assign line_address[CACHE_LINE_ADDR_WIDTH + CACHE_LINE_SIZE_WIDTH - 1:CACHE_LINE_SIZE_WIDTH] = tag_entry; |
assign line_address[CACHE_TAG_ADDR_HIGH:CACHE_TAG_ADDR_LOW] = tag_data_out[13:0]; |
assign line_address[CACHE_LINE_SIZE_WIDTH-1:0] = {CACHE_LINE_SIZE_WIDTH{1'b0}}; |
|
//----------------------------------------------------------------- |
// Control logic |
//----------------------------------------------------------------- |
always @ (posedge rst_i or posedge clk_i ) |
begin |
if (rst_i == 1'b1) |
begin |
data_w <= 32'h00000000; |
data_wr <= 4'h0; |
data_rd <= 1'b0; |
req_address <= 32'h00000000; |
req_ack <= 1'b0; |
req_wr <= 4'h0; |
req_rd <= 1'b0; |
tag_wr <= 1'b0; |
req_flush <= 1'b0; |
flush_single <= 1'b0; |
fill <= 1'b0; |
evict <= 1'b0; |
cache_data_w <= 32'h00000000; |
cache_wr <= 4'b0; |
ack <= 1'b0; |
state <= STATE_IDLE; |
end |
else |
begin |
ack <= 1'b0; |
tag_wr <= 1'b0; |
fill <= 1'b0; |
evict <= 1'b0; |
cache_wr <= 4'b0; |
data_wr <= 4'b0; |
data_rd <= 1'b0; |
|
if (flush_i) |
req_flush <= 1'b1; |
|
case (state) |
|
//----------------------------------------- |
// IDLE |
//----------------------------------------- |
STATE_IDLE : |
begin |
// Read (uncacheable) |
if (rd_i & ~cacheable) |
begin |
// Start read single from memory |
req_address <= address_i; |
req_address[ADDR_CACHE_BYPASS_BIT] <= 1'b0; |
data_rd <= 1'b1; |
req_rd <= 1'b1; |
req_wr <= 4'b0; |
req_ack <= 1'b1; |
state <= STATE_SINGLE; |
end |
// Read (cacheable) |
else if (rd_i) |
begin |
req_address <= address_i; |
req_rd <= 1'b1; |
req_wr <= 4'b0; |
req_ack <= 1'b1; |
state <= STATE_CHECK; |
end |
// Write (uncacheable) |
else if (wr_i != 4'b0000 & ~cacheable) |
begin |
// Perform write single |
req_address <= address_i; |
req_address[ADDR_CACHE_BYPASS_BIT] <= 1'b0; |
data_w <= data_i; |
data_wr <= wr_i; |
req_wr <= wr_i; |
req_rd <= 1'b0; |
req_ack <= 1'b1; |
state <= STATE_SINGLE; |
end |
// Write (cacheable) |
else if (wr_i != 4'b0000) |
begin |
req_address <= address_i; |
data_w <= data_i; |
req_wr <= wr_i; |
req_rd <= 1'b0; |
req_ack <= 1'b0; |
|
// Early ACK |
ack <= 1'b1; |
|
state <= STATE_WRITE; |
end |
// Cache flush request |
else if (flush_i | req_flush) |
begin |
// Set to first line address |
req_address <= 32'h00000000; |
req_flush <= 1'b0; |
req_ack <= 1'b0; |
flush_single<= 1'b0; |
state <= STATE_FLUSH2; |
end |
end |
//----------------------------------------- |
// WRITE - Wait for write-thru to complete |
//----------------------------------------- |
STATE_WRITE : |
begin |
// Cache hit |
if (valid && |
(req_address[CACHE_TAG_ADDR_HIGH:CACHE_TAG_ADDR_LOW] == tag_data_out[13:0])) |
begin |
// Update line already in cache |
cache_data_w <= data_w; |
cache_wr <= req_wr; |
|
// Mark line as dirty |
tag_data_in <= tag_data_out; |
tag_data_in[CACHE_TAG_DIRTY_BIT] <= 1'b1; |
tag_wr <= 1'b1; |
|
state <= STATE_WAIT2; |
end |
// Cache dirty |
else if (valid & dirty) |
begin |
// Evict cache line |
evict <= 1'b1; |
state <= STATE_EVICTING; |
end |
// Cache miss |
else |
begin |
// Update tag memory with this line's details |
tag_data_in <= {1'b1, 1'b1, req_address[CACHE_TAG_ADDR_HIGH:CACHE_TAG_ADDR_LOW]}; |
tag_wr <= 1'b1; |
|
// Fill cache line |
fill <= 1'b1; |
state <= STATE_UPDATE; |
end |
end |
//----------------------------------------- |
// EVICTING - Evicting cache line |
//----------------------------------------- |
STATE_EVICTING: |
begin |
// Data ready from memory? |
if (done) |
begin |
// Update tag memory with this new line's details |
tag_data_in <= {1'b1, 1'b0, req_address[CACHE_TAG_ADDR_HIGH:CACHE_TAG_ADDR_LOW]}; |
tag_wr <= 1'b1; |
|
// Fill cache line |
fill <= 1'b1; |
|
// Evict for read? |
if (req_rd) |
state <= STATE_FETCH; |
// Evict for write |
else |
state <= STATE_UPDATE; |
end |
end |
//----------------------------------------- |
// UPDATE - Update fetched cache line |
//----------------------------------------- |
STATE_UPDATE: |
begin |
// Data ready from memory? |
if (done) |
begin |
// Update line already in cache |
cache_data_w <= data_w; |
cache_wr <= req_wr; |
|
// Mark line as dirty |
tag_data_in <= tag_data_out; |
tag_data_in[CACHE_TAG_DIRTY_BIT] <= 1'b1; |
tag_wr <= 1'b1; |
|
state <= STATE_WAIT2; |
end |
end |
//----------------------------------------- |
// CHECK - check cache for hit or miss |
//----------------------------------------- |
STATE_CHECK : |
begin |
// Cache hit |
if (valid && |
(req_address[CACHE_TAG_ADDR_HIGH:CACHE_TAG_ADDR_LOW] == tag_data_out[13:0])) |
begin |
state <= STATE_IDLE; |
end |
// Cache dirty |
else if (valid & dirty) |
begin |
// Evict cache line |
evict <= 1'b1; |
state <= STATE_EVICTING; |
end |
// Cache miss |
else |
begin |
// Update tag memory with this line's details |
tag_data_in <= {1'b1, 1'b0, req_address[CACHE_TAG_ADDR_HIGH:CACHE_TAG_ADDR_LOW]}; |
tag_wr <= 1'b1; |
|
// Fill cache line |
fill <= 1'b1; |
state <= STATE_FETCH; |
end |
end |
//----------------------------------------- |
// FETCH_SINGLE - Single access to memory |
//----------------------------------------- |
STATE_SINGLE: |
begin |
// Data ready from memory? |
if (done) |
begin |
// Single WRITE? |
if (~req_rd) |
begin |
state <= STATE_SINGLE_READY; |
ack <= req_ack; |
end |
// Dirty? Write back |
else if (valid & dirty) |
begin |
// Evict cache line |
evict <= 1'b1; |
flush_single<= 1'b1; |
state <= STATE_FLUSH4; |
end |
// Valid line, invalidate |
else if (valid) |
begin |
tag_data_in <= tag_data_out; |
tag_data_in[CACHE_TAG_VALID_BIT] <= 1'b0; |
tag_wr <= 1'b1; |
|
state <= STATE_SINGLE_READY; |
ack <= req_ack; |
end |
else |
begin |
state <= STATE_SINGLE_READY; |
ack <= req_ack; |
end |
end |
end |
//----------------------------------------- |
// FETCH - Fetch row from memory |
//----------------------------------------- |
STATE_FETCH : |
begin |
// Cache line filled? |
if (done) |
state <= STATE_WAIT; |
end |
//----------------------------------------- |
// WAIT - Wait cycle |
//----------------------------------------- |
STATE_WAIT : |
begin |
// Allow extra wait state to handle write & read collision |
state <= STATE_WAIT2; |
end |
//----------------------------------------- |
// WAIT2 - Wait cycle |
//----------------------------------------- |
STATE_WAIT2 : |
begin |
state <= STATE_IDLE; |
ack <= req_ack; |
end |
//----------------------------------------- |
// SINGLE_READY - Uncached access ready |
//----------------------------------------- |
STATE_SINGLE_READY : |
begin |
// Allow extra wait state to handle write & read collision |
state <= STATE_IDLE; |
end |
//----------------------------------------- |
// FLUSHx - Flush dirty lines & invalidate |
//----------------------------------------- |
STATE_FLUSH1 : |
begin |
if (req_address[CACHE_LINE_ADDR_WIDTH + CACHE_LINE_SIZE_WIDTH - 1:CACHE_LINE_SIZE_WIDTH] == {CACHE_LINE_ADDR_WIDTH{1'b1}}) |
begin |
req_ack <= 1'b0; |
state <= STATE_WAIT; |
end |
else |
begin |
// Increment flush line address |
req_address[CACHE_LINE_ADDR_WIDTH + CACHE_LINE_SIZE_WIDTH - 1:CACHE_LINE_SIZE_WIDTH] <= |
req_address[CACHE_LINE_ADDR_WIDTH + CACHE_LINE_SIZE_WIDTH - 1:CACHE_LINE_SIZE_WIDTH] + 1; |
|
state <= STATE_FLUSH2; |
end |
end |
//----------------------------------------- |
// FLUSH2 - Wait state |
//----------------------------------------- |
STATE_FLUSH2 : |
begin |
// Allow a cycle to read line state |
state <= STATE_FLUSH3; |
end |
//----------------------------------------- |
// FLUSH3 - Check if line dirty & flush |
//----------------------------------------- |
STATE_FLUSH3 : |
begin |
// Dirty line? Evict line first |
if (dirty) |
begin |
// Evict cache line |
evict <= 1'b1; |
state <= STATE_FLUSH4; |
end |
// Not dirty? Just invalidate |
else |
begin |
tag_data_in <= tag_data_out; |
tag_data_in[CACHE_TAG_VALID_BIT] <= 1'b0; |
tag_wr <= 1'b1; |
|
if (flush_single) |
state <= STATE_WAIT; |
else |
state <= STATE_FLUSH1; |
end |
end |
//----------------------------------------- |
// FLUSH4 - Wait for line flush to complete |
//----------------------------------------- |
STATE_FLUSH4 : |
begin |
// Cache line filled? |
if (done) |
begin |
// Invalidate line |
tag_data_in <= tag_data_out; |
tag_data_in[CACHE_TAG_VALID_BIT] <= 1'b0; |
tag_data_in[CACHE_TAG_DIRTY_BIT] <= 1'b0; |
tag_wr <= 1'b1; |
|
if (flush_single) |
begin |
state <= STATE_SINGLE_READY; |
ack <= req_ack; |
end |
else |
state <= STATE_FLUSH1; |
end |
end |
default: |
; |
endcase |
end |
end |
|
//----------------------------------------------------------------- |
// Instantiation |
//----------------------------------------------------------------- |
|
altor32_dcache_mem_if |
#( |
.CACHE_LINE_SIZE_WIDTH(CACHE_LINE_SIZE_WIDTH), |
.CACHE_LINE_WORDS_IDX_MAX(CACHE_LINE_WORDS_IDX_MAX) |
) |
u_mem_if |
( |
.clk_i(clk_i), |
.rst_i(rst_i), |
|
// Cache interface |
.address_i(muxed_address), |
.data_i(data_w), |
.data_o(data_r), |
.fill_i(fill), |
.evict_i(evict), |
.evict_addr_i(line_address), |
.rd_single_i(data_rd), |
.wr_single_i(data_wr), |
.done_o(done), |
|
// Cache memory (fill/evict) |
.cache_addr_o(cache_update_addr), |
.cache_data_o(cache_update_data_w), |
.cache_data_i(cache_update_data_r), |
.cache_wr_o(cache_update_wr), |
|
// Memory interface (slave) |
.mem_addr_o(mem_addr_o), |
.mem_data_i(mem_data_i), |
.mem_data_o(mem_data_o), |
.mem_burst_o(mem_burst_o), |
.mem_rd_o(mem_rd_o), |
.mem_wr_o(mem_wr_o), |
.mem_accept_i(mem_accept_i), |
.mem_ack_i(mem_ack_i) |
); |
|
// Tag memory |
altor32_ram_sp |
#( |
.WIDTH(CACHE_TAG_WIDTH), |
.SIZE(CACHE_LINE_ADDR_WIDTH) |
) |
u1_tag_mem |
( |
.clk_i(clk_i), |
.dat_o(tag_data_out), |
.dat_i(tag_data_in), |
.adr_i(tag_entry), |
.wr_i(tag_wr) |
); |
|
// Data memory |
altor32_ram_dp |
#( |
.WIDTH(8), |
.SIZE(CACHE_DWIDTH) |
) |
u2_data_mem0 |
( |
.aclk_i(clk_i), |
.aadr_i(cache_address), |
.adat_o(cache_data_r[7:0]), |
.adat_i(cache_data_w[7:0]), |
.awr_i(cache_wr[0]), |
|
.bclk_i(clk_i), |
.badr_i(cache_update_addr[CACHE_DWIDTH+2-1:2]), |
.bdat_o(cache_update_data_r[7:0]), |
.bdat_i(cache_update_data_w[7:0]), |
.bwr_i(cache_update_wr) |
); |
|
altor32_ram_dp |
#( |
.WIDTH(8), |
.SIZE(CACHE_DWIDTH) |
) |
u2_data_mem1 |
( |
.aclk_i(clk_i), |
.aadr_i(cache_address), |
.adat_o(cache_data_r[15:8]), |
.adat_i(cache_data_w[15:8]), |
.awr_i(cache_wr[1]), |
|
.bclk_i(clk_i), |
.badr_i(cache_update_addr[CACHE_DWIDTH+2-1:2]), |
.bdat_o(cache_update_data_r[15:8]), |
.bdat_i(cache_update_data_w[15:8]), |
.bwr_i(cache_update_wr) |
); |
|
altor32_ram_dp |
#( |
.WIDTH(8), |
.SIZE(CACHE_DWIDTH) |
) |
u2_data_mem2 |
( |
.aclk_i(clk_i), |
.aadr_i(cache_address), |
.adat_o(cache_data_r[23:16]), |
.adat_i(cache_data_w[23:16]), |
.awr_i(cache_wr[2]), |
|
.bclk_i(clk_i), |
.badr_i(cache_update_addr[CACHE_DWIDTH+2-1:2]), |
.bdat_o(cache_update_data_r[23:16]), |
.bdat_i(cache_update_data_w[23:16]), |
.bwr_i(cache_update_wr) |
); |
|
altor32_ram_dp |
#( |
.WIDTH(8), |
.SIZE(CACHE_DWIDTH) |
) |
u2_data_mem3 |
( |
.aclk_i(clk_i), |
.aadr_i(cache_address), |
.adat_o(cache_data_r[31:24]), |
.adat_i(cache_data_w[31:24]), |
.awr_i(cache_wr[3]), |
|
.bclk_i(clk_i), |
.badr_i(cache_update_addr[CACHE_DWIDTH+2-1:2]), |
.bdat_o(cache_update_data_r[31:24]), |
.bdat_i(cache_update_data_w[31:24]), |
.bwr_i(cache_update_wr) |
); |
|
endmodule |
/rtl/cpu/altor32_noicache.v
0,0 → 1,126
//----------------------------------------------------------------- |
// AltOR32 |
// Alternative Lightweight OpenRisc |
// V2.0 |
// Ultra-Embedded.com |
// Copyright 2011 - 2013 |
// |
// Email: admin@ultra-embedded.com |
// |
// License: LGPL |
//----------------------------------------------------------------- |
// |
// Copyright (C) 2011 - 2013 Ultra-Embedded.com |
// |
// This source file may be used and distributed without |
// restriction provided that this copyright statement is not |
// removed from the file and that any derivative work contains |
// the original copyright notice and the associated disclaimer. |
// |
// This source file is free software; you can redistribute it |
// and/or modify it under the terms of the GNU Lesser General |
// Public License as published by the Free Software Foundation; |
// either version 2.1 of the License, or (at your option) any |
// later version. |
// |
// This source is distributed in the hope that it will be |
// useful, but WITHOUT ANY WARRANTY; without even the implied |
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR |
// PURPOSE. See the GNU Lesser General Public License for more |
// details. |
// |
// You should have received a copy of the GNU Lesser General |
// Public License along with this source; if not, write to the |
// Free Software Foundation, Inc., 59 Temple Place, Suite 330, |
// Boston, MA 02111-1307 USA |
//----------------------------------------------------------------- |
|
//----------------------------------------------------------------- |
// Includes |
//----------------------------------------------------------------- |
`include "altor32_defs.v" |
|
//----------------------------------------------------------------- |
// Module - Cache substitute (used when ICache disabled) |
//----------------------------------------------------------------- |
module altor32_noicache |
( |
input clk_i /*verilator public*/, |
input rst_i /*verilator public*/, |
|
// Processor interface |
input rd_i /*verilator public*/, |
input [31:0] pc_i /*verilator public*/, |
output [31:0] instruction_o /*verilator public*/, |
output valid_o /*verilator public*/, |
|
// Memory interface (slave) |
output reg [31:0] mem_addr_o /*verilator public*/, |
input [31:0] mem_data_i /*verilator public*/, |
output reg mem_burst_o /*verilator public*/, |
output reg mem_rd_o /*verilator public*/, |
input mem_accept_i/*verilator public*/, |
input mem_ack_i/*verilator public*/ |
); |
|
//----------------------------------------------------------------- |
// Registers / Wires |
//----------------------------------------------------------------- |
|
// Current state |
parameter STATE_CHECK = 0; |
parameter STATE_FETCH = 1; |
reg [1:0] state; |
|
assign valid_o = mem_ack_i; |
assign instruction_o = mem_data_i; |
|
//----------------------------------------------------------------- |
// Control logic |
//----------------------------------------------------------------- |
always @ (posedge rst_i or posedge clk_i ) |
begin |
if (rst_i == 1'b1) |
begin |
mem_addr_o <= 32'h00000000; |
mem_rd_o <= 1'b0; |
mem_burst_o <= 1'b0; |
state <= STATE_CHECK; |
end |
else |
begin |
|
if (mem_accept_i) |
mem_rd_o <= 1'b0; |
|
case (state) |
|
//----------------------------------------- |
// CHECK - check cache for hit or miss |
//----------------------------------------- |
STATE_CHECK : |
begin |
// Start fetch from memory |
mem_addr_o <= pc_i; |
mem_rd_o <= 1'b1; |
mem_burst_o <= 1'b0; |
state <= STATE_FETCH; |
end |
//----------------------------------------- |
// FETCH - Fetch row from memory |
//----------------------------------------- |
STATE_FETCH : |
begin |
// Data ready from memory? |
if (mem_ack_i) |
state <= STATE_CHECK; |
end |
|
default: |
; |
endcase |
end |
end |
|
endmodule |
|
/rtl/cpu/altor32_writeback.v
0,0 → 1,146
//----------------------------------------------------------------- |
// AltOR32 |
// Alternative Lightweight OpenRisc |
// V2.0 |
// Ultra-Embedded.com |
// Copyright 2011 - 2013 |
// |
// Email: admin@ultra-embedded.com |
// |
// License: LGPL |
//----------------------------------------------------------------- |
// |
// Copyright (C) 2011 - 2013 Ultra-Embedded.com |
// |
// This source file may be used and distributed without |
// restriction provided that this copyright statement is not |
// removed from the file and that any derivative work contains |
// the original copyright notice and the associated disclaimer. |
// |
// This source file is free software; you can redistribute it |
// and/or modify it under the terms of the GNU Lesser General |
// Public License as published by the Free Software Foundation; |
// either version 2.1 of the License, or (at your option) any |
// later version. |
// |
// This source is distributed in the hope that it will be |
// useful, but WITHOUT ANY WARRANTY; without even the implied |
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR |
// PURPOSE. See the GNU Lesser General Public License for more |
// details. |
// |
// You should have received a copy of the GNU Lesser General |
// Public License along with this source; if not, write to the |
// Free Software Foundation, Inc., 59 Temple Place, Suite 330, |
// Boston, MA 02111-1307 USA |
//----------------------------------------------------------------- |
|
//----------------------------------------------------------------- |
// Includes |
//----------------------------------------------------------------- |
`include "altor32_defs.v" |
|
//----------------------------------------------------------------- |
// Module - Writeback |
//----------------------------------------------------------------- |
module altor32_writeback |
( |
// General |
input clk_i /*verilator public*/, |
input rst_i /*verilator public*/, |
|
// Opcode |
input [31:0] opcode_i /*verilator public*/, |
|
// Register target |
input [4:0] rd_i /*verilator public*/, |
|
// ALU result |
input [31:0] alu_result_i /*verilator public*/, |
|
// Memory load result |
input [31:0] mem_result_i /*verilator public*/, |
input [1:0] mem_offset_i /*verilator public*/, |
input mem_ready_i /*verilator public*/, |
|
// Multiplier result |
input mult_i /*verilator public*/, |
input [31:0] mult_result_i /*verilator public*/, |
|
// Outputs |
output write_enable_o /*verilator public*/, |
output [4:0] write_addr_o /*verilator public*/, |
output [31:0] write_data_o /*verilator public*/ |
); |
|
//----------------------------------------------------------------- |
// Registers |
//----------------------------------------------------------------- |
|
// Register address |
reg [4:0] r_w_rd; |
|
// Register writeback value |
reg [31:0] r_result; |
|
reg [7:0] r_opcode; |
|
// Register writeback enable |
reg r_w_write_rd; |
|
//------------------------------------------------------------------- |
// Writeback |
//------------------------------------------------------------------- |
always @ (posedge clk_i or posedge rst_i) |
begin |
if (rst_i == 1'b1) |
begin |
r_w_write_rd <= 1'b1; |
r_result <= 32'h00000000; |
r_w_rd <= 5'b00000; |
r_opcode <= 8'b0; |
end |
else |
begin |
r_w_write_rd <= 1'b0; |
|
r_w_rd <= rd_i; |
r_result <= alu_result_i; |
|
r_opcode <= {2'b00,opcode_i[31:26]}; |
|
// Register writeback required? |
if (rd_i != 5'b00000) |
r_w_write_rd <= 1'b1; |
end |
end |
|
//------------------------------------------------------------------- |
// Load result resolve |
//------------------------------------------------------------------- |
wire load_insn; |
wire [31:0] load_result; |
|
altor32_lfu |
u_lfu |
( |
// Opcode |
.opcode_i(r_opcode), |
|
// Memory load result |
.mem_result_i(mem_result_i), |
.mem_offset_i(mem_offset_i), |
|
// Result |
.load_result_o(load_result), |
.load_insn_o(load_insn) |
); |
|
//------------------------------------------------------------------- |
// Assignments |
//------------------------------------------------------------------- |
assign write_enable_o = load_insn ? (r_w_write_rd & mem_ready_i) : r_w_write_rd; |
assign write_data_o = load_insn ? load_result : (mult_i ? mult_result_i : r_result); |
assign write_addr_o = r_w_rd; |
|
endmodule |
/rtl/cpu/altor32_icache.v
0,0 → 1,390
//----------------------------------------------------------------- |
// AltOR32 |
// Alternative Lightweight OpenRisc |
// V2.0 |
// Ultra-Embedded.com |
// Copyright 2011 - 2013 |
// |
// Email: admin@ultra-embedded.com |
// |
// License: LGPL |
//----------------------------------------------------------------- |
// |
// Copyright (C) 2011 - 2013 Ultra-Embedded.com |
// |
// This source file may be used and distributed without |
// restriction provided that this copyright statement is not |
// removed from the file and that any derivative work contains |
// the original copyright notice and the associated disclaimer. |
// |
// This source file is free software; you can redistribute it |
// and/or modify it under the terms of the GNU Lesser General |
// Public License as published by the Free Software Foundation; |
// either version 2.1 of the License, or (at your option) any |
// later version. |
// |
// This source is distributed in the hope that it will be |
// useful, but WITHOUT ANY WARRANTY; without even the implied |
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR |
// PURPOSE. See the GNU Lesser General Public License for more |
// details. |
// |
// You should have received a copy of the GNU Lesser General |
// Public License along with this source; if not, write to the |
// Free Software Foundation, Inc., 59 Temple Place, Suite 330, |
// Boston, MA 02111-1307 USA |
//----------------------------------------------------------------- |
|
//----------------------------------------------------------------- |
// Includes |
//----------------------------------------------------------------- |
`include "altor32_defs.v" |
|
//----------------------------------------------------------------- |
// Module - Instruction Cache |
//----------------------------------------------------------------- |
module altor32_icache |
( |
input clk_i /*verilator public*/, |
input rst_i /*verilator public*/, |
|
// Processor interface |
input rd_i /*verilator public*/, |
input [31:0] pc_i /*verilator public*/, |
output [31:0] instruction_o /*verilator public*/, |
output valid_o /*verilator public*/, |
input invalidate_i /*verilator public*/, |
|
// Status |
output miss_o /*verilator public*/, |
output busy_o /*verilator public*/, |
|
// Memory interface (slave) |
output [31:0] mem_addr_o /*verilator public*/, |
input [31:0] mem_data_i /*verilator public*/, |
output mem_burst_o /*verilator public*/, |
output mem_rd_o /*verilator public*/, |
input mem_accept_i/*verilator public*/, |
input mem_ack_i/*verilator public*/ |
); |
|
//----------------------------------------------------------------- |
// Params |
//----------------------------------------------------------------- |
parameter BOOT_VECTOR = 32'h00000000; |
|
parameter CACHE_LINE_SIZE_WIDTH = 5; /* 5-bits -> 32 entries */ |
parameter CACHE_LINE_SIZE_BYTES = 2 ** CACHE_LINE_SIZE_WIDTH; /* 32 bytes / 4 words per line */ |
parameter CACHE_LINE_ADDR_WIDTH = 8; /* 256 lines */ |
parameter CACHE_LINE_WORDS_IDX_MAX = CACHE_LINE_SIZE_WIDTH - 2; /* 3-bit = 111 */ |
parameter CACHE_TAG_ENTRIES = 2 ** CACHE_LINE_ADDR_WIDTH ; /* 256 tag entries */ |
parameter CACHE_DSIZE = CACHE_LINE_ADDR_WIDTH * CACHE_LINE_SIZE_BYTES; /* 8KB data */ |
parameter CACHE_DWIDTH = CACHE_LINE_ADDR_WIDTH + CACHE_LINE_SIZE_WIDTH - 2; /* 10-bits */ |
|
parameter CACHE_TAG_WIDTH = 16; /* 16-bit tag entry size */ |
parameter CACHE_TAG_LINE_ADDR_WIDTH = CACHE_TAG_WIDTH - 1; /* 15 bits of data (tag entry size minus valid bit) */ |
|
parameter CACHE_TAG_ADDR_LOW = CACHE_LINE_SIZE_WIDTH + CACHE_LINE_ADDR_WIDTH; |
parameter CACHE_TAG_ADDR_HIGH = CACHE_TAG_LINE_ADDR_WIDTH + CACHE_LINE_SIZE_WIDTH + CACHE_LINE_ADDR_WIDTH - 1; |
|
// Tag fields |
parameter CACHE_TAG_VALID_BIT = 15; |
|
// 31 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00 |
// |--------------| | | | | | | | | | | | | | | | | |
// +--------------------+ +-------------------+ +-----------+ |
// Tag entry Line address Address |
// (15-bits) (8-bits) within line |
// (5-bits) |
|
//----------------------------------------------------------------- |
// Registers / Wires |
//----------------------------------------------------------------- |
wire [CACHE_TAG_WIDTH-1:0] tag_data_out; |
reg [CACHE_TAG_WIDTH-1:0] tag_data_in; |
reg tag_wr; |
|
wire [CACHE_LINE_ADDR_WIDTH-1:0] tag_entry; |
wire [CACHE_DWIDTH-1:0] cache_address_rd; |
|
reg [CACHE_DWIDTH-1:0] cache_address_wr; |
reg [31:0] cache_data_w; |
reg cache_wr; |
|
reg [CACHE_LINE_SIZE_WIDTH-3:0] fetch_word; |
|
reg [31:0] last_pc; |
reg [31:0] miss_pc; |
|
wire busy_o; |
wire miss_o; |
|
reg initial_fetch; |
reg flush_req; |
|
reg [31:0] mem_addr_o; |
reg mem_rd_o; |
reg mem_burst_o; |
|
reg [CACHE_LINE_ADDR_WIDTH-1:0] flush_addr; |
reg flush_wr; |
|
reg read_while_busy; |
|
// Current state |
parameter STATE_CHECK = 0; |
parameter STATE_FETCH = 1; |
parameter STATE_WAIT = 2; |
parameter STATE_WAIT2 = 3; |
parameter STATE_FLUSH = 4; |
reg [3:0] state; |
|
assign tag_entry = (state != STATE_CHECK) ? miss_pc[CACHE_LINE_ADDR_WIDTH + CACHE_LINE_SIZE_WIDTH - 1:CACHE_LINE_SIZE_WIDTH] : pc_i[CACHE_LINE_ADDR_WIDTH + CACHE_LINE_SIZE_WIDTH - 1:CACHE_LINE_SIZE_WIDTH]; |
assign cache_address_rd = pc_i[CACHE_LINE_ADDR_WIDTH + CACHE_LINE_SIZE_WIDTH - 1:2]; |
|
assign miss_o = (!tag_data_out[CACHE_TAG_VALID_BIT] || (last_pc[CACHE_TAG_ADDR_HIGH:CACHE_TAG_ADDR_LOW] != tag_data_out[14:0])) ? 1'b1: 1'b0; |
|
wire valid_o = !miss_o && !busy_o; |
|
//----------------------------------------------------------------- |
// Control logic |
//----------------------------------------------------------------- |
reg [CACHE_LINE_SIZE_WIDTH-3:0] v_line_word; |
|
always @ (posedge rst_i or posedge clk_i ) |
begin |
if (rst_i == 1'b1) |
begin |
fetch_word <= {CACHE_LINE_SIZE_WIDTH-2{1'b0}}; |
mem_addr_o <= 32'h00000000; |
mem_rd_o <= 1'b0; |
mem_burst_o <= 1'b0; |
tag_wr <= 1'b0; |
cache_address_wr<= {CACHE_DWIDTH{1'b0}}; |
cache_data_w <= 32'h00000000; |
cache_wr <= 1'b0; |
miss_pc <= BOOT_VECTOR + `VECTOR_RESET; |
last_pc <= 32'h00000000; |
state <= STATE_CHECK; |
initial_fetch <= 1'b1; |
read_while_busy <= 1'b0; |
|
flush_addr <= {CACHE_LINE_ADDR_WIDTH{1'b0}}; |
flush_wr <= 1'b0; |
flush_req <= 1'b0; |
end |
else |
begin |
|
if (mem_accept_i) |
mem_rd_o <= 1'b0; |
tag_wr <= 1'b0; |
cache_wr <= 1'b0; |
initial_fetch <= 1'b0; |
flush_wr <= 1'b0; |
last_pc <= pc_i; |
|
// Latch invalidate request even if can't be actioned now... |
if (invalidate_i) |
flush_req <= 1'b1; |
|
// New request whilst cache busy? |
if (rd_i) |
read_while_busy <= 1'b1; |
|
case (state) |
|
//----------------------------------------- |
// CHECK - check cache for hit or miss |
//----------------------------------------- |
STATE_CHECK : |
begin |
// Cache flush request pending? |
if (flush_req || invalidate_i) |
begin |
flush_req <= 1'b0; |
flush_addr <= {CACHE_LINE_ADDR_WIDTH{1'b1}}; |
flush_wr <= 1'b1; |
state <= STATE_FLUSH; |
|
`ifdef CONF_CORE_DEBUG |
$display("Fetch: Cache flush request"); |
`endif |
end |
// Cache miss (& new read request not pending) |
else if ((miss_o && !initial_fetch) && !rd_i && !read_while_busy) |
begin |
read_while_busy <= 1'b0; |
|
fetch_word <= {CACHE_LINE_SIZE_WIDTH-2{1'b0}}; |
|
`ifdef CONF_CORE_DEBUG |
$display("Fetch: Cache miss at 0x%x (last=%x, current=%x)", miss_pc, last_pc, pc_i); |
`endif |
|
// Start fetch from memory |
mem_addr_o <= {miss_pc[31:CACHE_LINE_SIZE_WIDTH], {CACHE_LINE_SIZE_WIDTH{1'b0}}}; |
mem_rd_o <= 1'b1; |
mem_burst_o <= 1'b1; |
state <= STATE_FETCH; |
|
// Update tag memory with this line's details |
tag_data_in <= {1'b1, miss_pc[CACHE_TAG_ADDR_HIGH:CACHE_TAG_ADDR_LOW]}; |
tag_wr <= 1'b1; |
end |
// Cache hit (or new read request) |
else |
begin |
`ifdef CONF_CORE_DEBUG |
$display("Fetch: Cache hit at PC=%x (current=%x)", last_pc, pc_i); |
if (read_while_busy) |
$display("Fetch: Read request whilst busy PC=%x (current=%x)", last_pc, pc_i); |
`endif |
|
// Store fetch PC |
miss_pc <= pc_i; |
state <= STATE_CHECK; |
read_while_busy <= 1'b0; |
end |
end |
//----------------------------------------- |
// FETCH - Fetch row from memory |
//----------------------------------------- |
STATE_FETCH : |
begin |
// Data ready from memory? |
if (mem_ack_i) |
begin |
// Write data into cache |
cache_address_wr<= {miss_pc[CACHE_LINE_ADDR_WIDTH + CACHE_LINE_SIZE_WIDTH - 1:CACHE_LINE_SIZE_WIDTH], fetch_word}; |
cache_data_w <= mem_data_i; |
cache_wr <= 1'b1; |
|
// Line fetch complete? |
if (fetch_word == {CACHE_LINE_WORDS_IDX_MAX{1'b1}}) |
begin |
state <= STATE_WAIT; |
end |
// Fetch next word for line |
else |
begin |
v_line_word = fetch_word + 1'b1; |
fetch_word <= v_line_word; |
|
mem_addr_o <= {mem_addr_o[31:CACHE_LINE_SIZE_WIDTH], v_line_word, 2'b00}; |
mem_rd_o <= 1'b1; |
|
if (fetch_word == ({CACHE_LINE_WORDS_IDX_MAX{1'b1}}-1)) |
begin |
mem_burst_o <= 1'b0; |
end |
end |
end |
end |
//----------------------------------------- |
// FLUSH - Invalidate tag memory |
//----------------------------------------- |
STATE_FLUSH : |
begin |
if (flush_addr == {CACHE_LINE_ADDR_WIDTH{1'b0}}) |
begin |
// Fetch current PC line again |
mem_addr_o <= {pc_i[31:CACHE_LINE_SIZE_WIDTH], {CACHE_LINE_SIZE_WIDTH{1'b0}}}; |
mem_rd_o <= 1'b1; |
mem_burst_o <= 1'b1; |
state <= STATE_FETCH; |
|
// Update tag memory with this line's details |
tag_data_in <= {1'b1, pc_i[CACHE_TAG_ADDR_HIGH:CACHE_TAG_ADDR_LOW]}; |
tag_wr <= 1'b1; |
|
// Start of line |
fetch_word <= {CACHE_LINE_SIZE_WIDTH-2{1'b0}}; |
|
// Clear pending reads whilst busy |
read_while_busy <= 1'b0; |
end |
else |
begin |
flush_addr <= flush_addr - 1; |
flush_wr <= 1'b1; |
state <= STATE_FLUSH; |
end |
end |
//----------------------------------------- |
// WAIT - Wait cycle |
//----------------------------------------- |
STATE_WAIT : |
begin |
// Allow extra wait state to handle write & read collision |
state <= STATE_WAIT2; |
end |
//----------------------------------------- |
// WAIT2 - Wait cycle |
//----------------------------------------- |
STATE_WAIT2 : |
begin |
`ifdef CONF_CORE_DEBUG |
$display("Fetch: Filled line containing PC=%x", miss_pc); |
`endif |
state <= STATE_CHECK; |
end |
|
|
default: |
; |
endcase |
end |
end |
|
// Stall the CPU if cache state machine is not idle! |
assign busy_o = (state == STATE_CHECK & ~read_while_busy) ? 1'b0 : 1'b1; |
|
//----------------------------------------------------------------- |
// Instantiation |
//----------------------------------------------------------------- |
|
// Tag memory |
altor32_ram_dp |
#( |
.WIDTH(CACHE_TAG_WIDTH), |
.SIZE(CACHE_LINE_ADDR_WIDTH) |
) |
u1_tag_mem |
( |
.aclk_i(clk_i), |
.adat_o(tag_data_out), |
.adat_i(tag_data_in), |
.aadr_i(tag_entry), |
.awr_i(tag_wr), |
|
.bclk_i(clk_i), |
.badr_i(flush_addr), |
.bdat_o(/*open*/), |
.bdat_i({CACHE_TAG_WIDTH{1'b0}}), |
.bwr_i(flush_wr) |
); |
|
// Data memory |
altor32_ram_dp |
#( |
.WIDTH(32), |
.SIZE(CACHE_DWIDTH) |
) |
u2_data_mem |
( |
.aclk_i(clk_i), |
.aadr_i(cache_address_rd), |
.adat_o(instruction_o), |
.adat_i(32'h00), |
.awr_i(1'b0), |
|
.bclk_i(clk_i), |
.badr_i(cache_address_wr), |
.bdat_o(/*open*/), |
.bdat_i(cache_data_w), |
.bwr_i(cache_wr) |
); |
|
endmodule |
|
/rtl/cpu/altor32_regfile_alt.v
0,0 → 1,195
//----------------------------------------------------------------- |
// AltOR32 |
// Alternative Lightweight OpenRisc |
// V2.0 |
// Ultra-Embedded.com |
// Copyright 2011 - 2013 |
// |
// Email: admin@ultra-embedded.com |
// |
// License: LGPL |
//----------------------------------------------------------------- |
// |
// Copyright (C) 2011 - 2013 Ultra-Embedded.com |
// |
// This source file may be used and distributed without |
// restriction provided that this copyright statement is not |
// removed from the file and that any derivative work contains |
// the original copyright notice and the associated disclaimer. |
// |
// This source file is free software; you can redistribute it |
// and/or modify it under the terms of the GNU Lesser General |
// Public License as published by the Free Software Foundation; |
// either version 2.1 of the License, or (at your option) any |
// later version. |
// |
// This source is distributed in the hope that it will be |
// useful, but WITHOUT ANY WARRANTY; without even the implied |
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR |
// PURPOSE. See the GNU Lesser General Public License for more |
// details. |
// |
// You should have received a copy of the GNU Lesser General |
// Public License along with this source; if not, write to the |
// Free Software Foundation, Inc., 59 Temple Place, Suite 330, |
// Boston, MA 02111-1307 USA |
//----------------------------------------------------------------- |
|
//----------------------------------------------------------------- |
// Includes |
//----------------------------------------------------------------- |
`include "altor32_defs.v" |
|
//----------------------------------------------------------------- |
// Module - Altera LPM register file |
//----------------------------------------------------------------- |
module altor32_regfile_alt |
( |
input clk_i /*verilator public*/, |
input rst_i /*verilator public*/, |
input wr_i /*verilator public*/, |
input [4:0] rs_i /*verilator public*/, |
input [4:0] rt_i /*verilator public*/, |
input [4:0] rd_i /*verilator public*/, |
output [31:0] reg_rs_o /*verilator public*/, |
output [31:0] reg_rt_o /*verilator public*/, |
input [31:0] reg_rd_i /*verilator public*/ |
); |
|
//----------------------------------------------------------------- |
// Params |
//----------------------------------------------------------------- |
parameter SUPPORT_32REGS = "ENABLED"; |
|
//----------------------------------------------------------------- |
// Registers |
//----------------------------------------------------------------- |
reg clk_delayed; |
wire [31:0] data_out1; |
wire [31:0] data_out2; |
reg write_enable; |
|
reg [31:0] reg_rs_o; |
reg [31:0] reg_rt_o; |
|
reg [4:0] addr_reg; |
reg [31:0] data_reg; |
|
wire [31:0] q1; |
wire [31:0] q2; |
|
//----------------------------------------------------------------- |
// Async Read Process |
//----------------------------------------------------------------- |
always @ (clk_i or rs_i or rt_i or rd_i or reg_rd_i or data_out1 or data_out2 or rst_i or wr_i) |
begin |
// Read Rs |
if (rs_i == 5'b00000) |
reg_rs_o <= 32'h00000000; |
else |
reg_rs_o <= data_out1; |
|
// Read Rt |
if (rt_i == 5'b00000) |
reg_rt_o <= 32'h00000000; |
else |
reg_rt_o <= data_out2; |
|
// Write enabled? |
if ((rd_i != 5'b00000) & (wr_i == 1'b1)) |
write_enable <= 1'b1; |
else |
write_enable <= 1'b0; |
end |
|
//----------------------------------------------------------------- |
// Sync addr & data |
//----------------------------------------------------------------- |
always @ (posedge clk_i or posedge rst_i) |
begin |
if (rst_i) |
begin |
addr_reg <= 5'b00000; |
data_reg <= 32'h00000000; |
|
end |
else |
begin |
addr_reg <= rd_i; |
data_reg <= reg_rd_i; |
end |
end |
|
//----------------------------------------------------------------- |
// Register File (using lpm_ram_dp) |
// Unfortunatly, LPM_RAM_DP primitives have synchronous read ports. |
// As this core requires asynchronous/non-registered read ports, |
// we have to invert the readclock edge to get close to what we |
// require. |
// This will have negative timing implications! |
//----------------------------------------------------------------- |
lpm_ram_dp |
#( |
.lpm_width(32), |
.lpm_widthad(5), |
.lpm_indata("REGISTERED"), |
.lpm_outdata("UNREGISTERED"), |
.lpm_rdaddress_control("REGISTERED"), |
.lpm_wraddress_control("REGISTERED"), |
.lpm_file("UNUSED"), |
.lpm_type("lpm_ram_dp"), |
.lpm_hint("UNUSED") |
) |
lpm1 |
( |
.rdclock(clk_delayed), |
.rdclken(1'b1), |
.rdaddress(rs_i), |
.rden(1'b1), |
.data(reg_rd_i), |
.wraddress(rd_i), |
.wren(write_enable), |
.wrclock(clk_i), |
.wrclken(1'b1), |
.q(q1) |
); |
|
|
lpm_ram_dp |
#( |
.lpm_width(32), |
.lpm_widthad(5), |
.lpm_indata("REGISTERED"), |
.lpm_outdata("UNREGISTERED"), |
.lpm_rdaddress_control("REGISTERED"), |
.lpm_wraddress_control("REGISTERED"), |
.lpm_file("UNUSED"), |
.lpm_type("lpm_ram_dp"), |
.lpm_hint("UNUSED") |
) |
lpm2 |
( |
.rdclock(clk_delayed), |
.rdclken(1'b1), |
.rdaddress(rt_i), |
.rden(1'b1), |
.data(reg_rd_i), |
.wraddress(rd_i), |
.wren(write_enable), |
.wrclock(clk_i), |
.wrclken(1'b1), |
.q(q2) |
); |
|
//----------------------------------------------------------------- |
// Combinatorial Assignments |
//----------------------------------------------------------------- |
|
// Delayed clock |
assign clk_delayed = !clk_i; |
|
// Reads are bypassed during write-back |
assign data_out1 = (rs_i != addr_reg) ? q1 : data_reg; |
assign data_out2 = (rt_i != addr_reg) ? q2 : data_reg; |
|
endmodule |
/rtl/cpu/altor32_dfu.v
0,0 → 1,206
//----------------------------------------------------------------- |
// AltOR32 |
// Alternative Lightweight OpenRisc |
// V2.0 |
// Ultra-Embedded.com |
// Copyright 2011 - 2013 |
// |
// Email: admin@ultra-embedded.com |
// |
// License: LGPL |
//----------------------------------------------------------------- |
// |
// Copyright (C) 2011 - 2013 Ultra-Embedded.com |
// |
// This source file may be used and distributed without |
// restriction provided that this copyright statement is not |
// removed from the file and that any derivative work contains |
// the original copyright notice and the associated disclaimer. |
// |
// This source file is free software; you can redistribute it |
// and/or modify it under the terms of the GNU Lesser General |
// Public License as published by the Free Software Foundation; |
// either version 2.1 of the License, or (at your option) any |
// later version. |
// |
// This source is distributed in the hope that it will be |
// useful, but WITHOUT ANY WARRANTY; without even the implied |
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR |
// PURPOSE. See the GNU Lesser General Public License for more |
// details. |
// |
// You should have received a copy of the GNU Lesser General |
// Public License along with this source; if not, write to the |
// Free Software Foundation, Inc., 59 Temple Place, Suite 330, |
// Boston, MA 02111-1307 USA |
//----------------------------------------------------------------- |
|
//----------------------------------------------------------------- |
// Includes |
//----------------------------------------------------------------- |
`include "altor32_defs.v" |
|
//----------------------------------------------------------------- |
// Module: Data Forwarding Unit |
//----------------------------------------------------------------- |
module altor32_dfu |
( |
// Input registers |
input [4:0] ra_i /*verilator public*/, |
input [4:0] rb_i /*verilator public*/, |
|
// Input register contents |
input [31:0] ra_regval_i /*verilator public*/, |
input [31:0] rb_regval_i /*verilator public*/, |
|
// Dest register (EXEC stage) |
input [4:0] rd_ex_i/*verilator public*/, |
|
// Dest register (WB stage) |
input [4:0] rd_wb_i/*verilator public*/, |
|
// Load pending / target |
input load_pending_i /*verilator public*/, |
input [4:0] rd_load_i /*verilator public*/, |
|
// Multiplier status |
input mult_lo_ex_i /*verilator public*/, |
input mult_hi_ex_i /*verilator public*/, |
input mult_lo_wb_i /*verilator public*/, |
input mult_hi_wb_i /*verilator public*/, |
|
// Multiplier result |
input [63:0] result_mult_i /*verilator public*/, |
|
// Result (EXEC) |
input [31:0] result_ex_i /*verilator public*/, |
|
// Result (WB) |
input [31:0] result_wb_i /*verilator public*/, |
|
// Resolved register values |
output reg [31:0] result_ra_o /*verilator public*/, |
output reg [31:0] result_rb_o /*verilator public*/, |
|
// Stall due to failed resolve |
output reg stall_o /*verilator public*/ |
); |
|
//------------------------------------------------------------------- |
// Data forwarding unit |
//------------------------------------------------------------------- |
always @ * |
begin |
// Default to no forwarding |
result_ra_o = ra_regval_i; |
result_rb_o = rb_regval_i; |
stall_o = 1'b0; |
|
//--------------------------------------------------------------- |
// RA - Hazard detection & forwarding |
//--------------------------------------------------------------- |
|
// Register[ra] hazard detection & forwarding logic |
// (higher priority = latest results!) |
if (ra_i != 5'b00000) |
begin |
//--------------------------------------------------------------- |
// RA from load (result not ready) |
//--------------------------------------------------------------- |
if (ra_i == rd_load_i & load_pending_i) |
begin |
stall_o = 1'b1; |
`ifdef CONF_CORE_DEBUG |
$display(" rA[%d] not ready as load still pending", ra_i); |
`endif |
end |
//--------------------------------------------------------------- |
// RA from PC-4 (exec) |
//--------------------------------------------------------------- |
else if (ra_i == rd_ex_i) |
begin |
// Multiplier has one cycle latency, stall if needed now |
if (mult_lo_ex_i | mult_hi_wb_i) |
stall_o = 1'b1; |
else |
begin |
result_ra_o = result_ex_i; |
`ifdef CONF_CORE_DEBUG |
$display(" rA[%d] forwarded 0x%08x (PC-4)", ra_i, result_ra_o); |
`endif |
end |
end |
//--------------------------------------------------------------- |
// RA from PC-8 (writeback) |
//--------------------------------------------------------------- |
else if (ra_i == rd_wb_i) |
begin |
if (mult_hi_wb_i) |
result_ra_o = result_mult_i[63:32]; |
else if (mult_lo_wb_i) |
result_ra_o = result_mult_i[31:0]; |
else |
result_ra_o = result_wb_i; |
|
`ifdef CONF_CORE_DEBUG |
$display(" rA[%d] forwarded 0x%08x (PC-8)", ra_i, result_ra_o); |
`endif |
end |
end |
|
//--------------------------------------------------------------- |
// RB - Hazard detection & forwarding |
//--------------------------------------------------------------- |
|
// Register[rb] hazard detection & forwarding logic |
// (higher priority = latest results!) |
if (rb_i != 5'b00000) |
begin |
|
//--------------------------------------------------------------- |
// RB from load (result not ready) |
//--------------------------------------------------------------- |
if (rb_i == rd_load_i & load_pending_i) |
begin |
stall_o = 1'b1; |
`ifdef CONF_CORE_DEBUG |
$display(" rB[%d] not ready as load still pending", rb_i); |
`endif |
end |
//--------------------------------------------------------------- |
// RB from PC-4 (exec) |
//--------------------------------------------------------------- |
else if (rb_i == rd_ex_i) |
begin |
// Multiplier has one cycle latency, stall if needed now |
if (mult_lo_ex_i | mult_hi_wb_i) |
stall_o = 1'b1; |
else |
begin |
result_rb_o = result_ex_i; |
|
`ifdef CONF_CORE_DEBUG |
$display(" rB[%d] forwarded 0x%08x (PC-4)", rb_i, result_rb_o); |
`endif |
end |
end |
//--------------------------------------------------------------- |
// RB from PC-8 (writeback) |
//--------------------------------------------------------------- |
else if (rb_i == rd_wb_i) |
begin |
if (mult_hi_wb_i) |
result_rb_o = result_mult_i[63:32]; |
else if (mult_lo_wb_i) |
result_rb_o = result_mult_i[31:0]; |
else |
result_rb_o = result_wb_i; |
|
`ifdef CONF_CORE_DEBUG |
$display(" rB[%d] forwarded 0x%08x (PC-8)", rb_i, result_rb_o); |
`endif |
end |
end |
end |
|
endmodule |
/rtl/cpu/altor32_funcs.v
0,0 → 1,253
//----------------------------------------------------------------- |
// AltOR32 |
// Alternative Lightweight OpenRisc |
// V2.0 |
// Ultra-Embedded.com |
// Copyright 2011 - 2013 |
// |
// Email: admin@ultra-embedded.com |
// |
// License: LGPL |
//----------------------------------------------------------------- |
// |
// Copyright (C) 2011 - 2013 Ultra-Embedded.com |
// |
// This source file may be used and distributed without |
// restriction provided that this copyright statement is not |
// removed from the file and that any derivative work contains |
// the original copyright notice and the associated disclaimer. |
// |
// This source file is free software; you can redistribute it |
// and/or modify it under the terms of the GNU Lesser General |
// Public License as published by the Free Software Foundation; |
// either version 2.1 of the License, or (at your option) any |
// later version. |
// |
// This source is distributed in the hope that it will be |
// useful, but WITHOUT ANY WARRANTY; without even the implied |
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR |
// PURPOSE. See the GNU Lesser General Public License for more |
// details. |
// |
// You should have received a copy of the GNU Lesser General |
// Public License along with this source; if not, write to the |
// Free Software Foundation, Inc., 59 Temple Place, Suite 330, |
// Boston, MA 02111-1307 USA |
//----------------------------------------------------------------- |
|
//----------------------------------------------------------------- |
// less_than_signed: Less than operator (signed) |
// Inputs: x = left operand, y = right operand |
// Return: (int)x < (int)y |
//----------------------------------------------------------------- |
function [0:0] less_than_signed; |
input [31:0] x; |
input [31:0] y; |
reg [31:0] v; |
begin |
v = (x - y); |
if (x[31] != y[31]) |
less_than_signed = x[31]; |
else |
less_than_signed = v[31]; |
end |
endfunction |
|
//----------------------------------------------------------------- |
// less_than_equal_signed: Less than or equal to operator (signed) |
// Inputs: x = left operand, y = right operand |
// Return: (int)x <= (int)y |
//----------------------------------------------------------------- |
function [0:0] less_than_equal_signed; |
input [31:0] x; |
input [31:0] y; |
reg [31:0] v; |
begin |
v = (x - y); |
if (x == y) |
less_than_equal_signed = 1'b1; |
else if (x[31] != y[31]) |
less_than_equal_signed = x[31]; |
else |
less_than_equal_signed = v[31]; |
end |
endfunction |
|
//----------------------------------------------------------------- |
// greater_than_signed: Greater than operator (signed) |
// Inputs: x = left operand, y = right operand |
// Return: (int)x > (int)y |
//----------------------------------------------------------------- |
function [0:0] greater_than_signed; |
input [31:0] x; |
input [31:0] y; |
reg [31:0] v; |
begin |
v = (y - x); |
if (x[31] != y[31]) |
greater_than_signed = y[31]; |
else |
greater_than_signed = v[31]; |
end |
endfunction |
|
//----------------------------------------------------------------- |
// greater_than_equal_signed: Greater than or equal to operator (signed) |
// Inputs: x = left operand, y = right operand |
// Return: (int)x >= (int)y |
//----------------------------------------------------------------- |
function [0:0] greater_than_equal_signed; |
input [31:0] x; |
input [31:0] y; |
reg [31:0] v; |
begin |
v = (y - x); |
if (x == y) |
greater_than_equal_signed = 1'b1; |
else if (x[31] != y[31]) |
greater_than_equal_signed = y[31]; |
else |
greater_than_equal_signed = v[31]; |
end |
endfunction |
|
//----------------------------------------------------------------- |
// sign_extend_imm16: Extend 16-bit signed value to 32-bit signed. |
// Inputs: x = operand |
// Return: (int)((short)x) |
//----------------------------------------------------------------- |
function [31:0] sign_extend_imm16; |
input [15:0] x; |
reg [31:0] y; |
begin |
if (x[15] == 1'b0) |
y[31:16] = 16'b0000000000000000; |
else |
y[31:16] = 16'b1111111111111111; |
|
y[15:0] = x; |
sign_extend_imm16 = y; |
end |
endfunction |
|
//----------------------------------------------------------------- |
// sign_extend_imm26: Extend 26-bit signed value to 32-bit signed. |
// Inputs: x = operand |
// Return: (int)((short)x) |
//----------------------------------------------------------------- |
function [31:0] sign_extend_imm26; |
input [25:0] x; |
reg [31:0] y; |
begin |
if (x[25] == 1'b0) |
y[31:26] = 6'b000000; |
else |
y[31:26] = 6'b111111; |
|
y[25:0] = x; |
sign_extend_imm26 = y; |
end |
endfunction |
|
//----------------------------------------------------------------- |
// extend_imm16: Extend 16-bit unsigned value to 32-bit unsigned. |
// Inputs: x = operand |
// Return: (unsigned int)x |
//----------------------------------------------------------------- |
function [31:0] extend_imm16; |
input [15:0] x; |
begin |
extend_imm16 = {16'h0000,x}; |
end |
endfunction |
|
//----------------------------------------------------------------- |
// less_than_zero: Is signed value less than 0? |
// Inputs: x = operand |
// Return: ((int)x) < 0 |
//----------------------------------------------------------------- |
function [0:0] less_than_zero; |
input [31:0] x; |
begin |
if ((x != 32'h00000000) & (x[31] == 1'b1)) |
less_than_zero = 1'b1; |
else |
less_than_zero = 1'b0; |
end |
endfunction |
|
//----------------------------------------------------------------- |
// less_than_equal_zero: Is signed value less than or equal to 0? |
// Inputs: x = operand |
// Return: ((int)x) <= 0 |
//----------------------------------------------------------------- |
function [0:0] less_than_equal_zero; |
input [31:0] x; |
begin |
if ((x == 32'h00000000) | (x[31] == 1'b1)) |
less_than_equal_zero = 1'b1; |
else |
less_than_equal_zero = 1'b0; |
end |
endfunction |
|
//----------------------------------------------------------------- |
// more_than_equal_zero: Is signed value more than or equal to 0? |
// Inputs: x = operand |
// Return: ((int)x) >= 0 |
//----------------------------------------------------------------- |
function [0:0] more_than_equal_zero; |
input [31:0] x; |
begin |
if ((x == 32'h00000000) | (x[31] == 1'b0)) |
more_than_equal_zero = 1'b1; |
else |
more_than_equal_zero = 1'b0; |
end |
endfunction |
|
//----------------------------------------------------------------- |
// more_than_equal_zero: Is signed value more than 0? |
// Inputs: x = operand |
// Return: ((int)x) > 0 |
//----------------------------------------------------------------- |
function [0:0] more_than_zero; |
input [31:0] x; |
begin |
if (((x != 32'h00000000) & (x[31] == 1'b0))) |
more_than_zero = 1'b1; |
else |
more_than_zero = 1'b0; |
end |
endfunction |
|
//----------------------------------------------------------------- |
// is_load_operation: Is this opcode a load operation? |
// Inputs: opcode |
// Return: 1 or 0 |
//----------------------------------------------------------------- |
function [0:0] is_load_operation; |
input [7:0] opcode; |
begin |
is_load_operation = (opcode == `INST_OR32_LBS || |
opcode == `INST_OR32_LBZ || |
opcode == `INST_OR32_LHS || |
opcode == `INST_OR32_LHZ || |
opcode == `INST_OR32_LWZ || |
opcode == `INST_OR32_LWS) ? 1'b1 : 1'b0; |
end |
endfunction |
|
//----------------------------------------------------------------- |
// is_store_operation: Is this opcode a store operation? |
// Inputs: opcode |
// Return: 1 or 0 |
//----------------------------------------------------------------- |
function [0:0] is_store_operation; |
input [7:0] opcode; |
begin |
is_store_operation = (opcode == `INST_OR32_SB || |
opcode == `INST_OR32_SH || |
opcode == `INST_OR32_SW) ? 1'b1 : 1'b0; |
end |
endfunction |
/rtl/cpu/altor32.v
0,0 → 1,475
//----------------------------------------------------------------- |
// AltOR32 |
// Alternative Lightweight OpenRisc |
// V2.0 |
// Ultra-Embedded.com |
// Copyright 2011 - 2013 |
// |
// Email: admin@ultra-embedded.com |
// |
// License: LGPL |
//----------------------------------------------------------------- |
// |
// Copyright (C) 2011 - 2013 Ultra-Embedded.com |
// |
// This source file may be used and distributed without |
// restriction provided that this copyright statement is not |
// removed from the file and that any derivative work contains |
// the original copyright notice and the associated disclaimer. |
// |
// This source file is free software; you can redistribute it |
// and/or modify it under the terms of the GNU Lesser General |
// Public License as published by the Free Software Foundation; |
// either version 2.1 of the License, or (at your option) any |
// later version. |
// |
// This source is distributed in the hope that it will be |
// useful, but WITHOUT ANY WARRANTY; without even the implied |
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR |
// PURPOSE. See the GNU Lesser General Public License for more |
// details. |
// |
// You should have received a copy of the GNU Lesser General |
// Public License along with this source; if not, write to the |
// Free Software Foundation, Inc., 59 Temple Place, Suite 330, |
// Boston, MA 02111-1307 USA |
//----------------------------------------------------------------- |
|
//----------------------------------------------------------------- |
// Includes |
//----------------------------------------------------------------- |
`include "altor32_defs.v" |
|
//----------------------------------------------------------------- |
// Module - AltOR32 CPU |
//----------------------------------------------------------------- |
module cpu |
( |
// General |
input clk_i /*verilator public*/, |
input rst_i /*verilator public*/, |
|
input intr_i /*verilator public*/, |
input nmi_i /*verilator public*/, |
output fault_o /*verilator public*/, |
output break_o /*verilator public*/, |
|
// Instruction memory |
output [31:0] imem_addr_o /*verilator public*/, |
output imem_rd_o /*verilator public*/, |
output imem_burst_o /*verilator public*/, |
input [31:0] imem_data_in_i /*verilator public*/, |
input imem_accept_i /*verilator public*/, |
input imem_ack_i /*verilator public*/, |
|
// Data memory |
output [31:0] dmem_addr_o /*verilator public*/, |
output [31:0] dmem_data_out_o /*verilator public*/, |
input [31:0] dmem_data_in_i /*verilator public*/, |
output [3:0] dmem_wr_o /*verilator public*/, |
output dmem_rd_o /*verilator public*/, |
output dmem_burst_o /*verilator public*/, |
input dmem_accept_i /*verilator public*/, |
input dmem_ack_i /*verilator public*/ |
); |
|
//----------------------------------------------------------------- |
// Params |
//----------------------------------------------------------------- |
parameter BOOT_VECTOR = 32'h00000000; |
parameter ISR_VECTOR = 32'h00000000; |
parameter REGISTER_FILE_TYPE = "SIMULATION"; |
parameter ENABLE_ICACHE = "ENABLED"; |
parameter ENABLE_DCACHE = "DISABLED"; |
parameter SUPPORT_32REGS = "ENABLED"; |
|
//----------------------------------------------------------------- |
// Registers / Wires |
//----------------------------------------------------------------- |
|
// Register number (rA) |
wire [4:0] w_ra; |
|
// Register number (rB) |
wire [4:0] w_rb; |
|
// Destination register number (pre execute stage) |
wire [4:0] w_rd; |
|
// Destination register number (post execute stage) |
wire [4:0] w_e_rd; |
|
// Register value (rA) |
wire [31:0] w_reg_ra; |
|
// Register value (rB) |
wire [31:0] w_reg_rb; |
|
// Current opcode |
wire [31:0] w_d_opcode; |
wire [31:0] w_d_pc; |
wire w_d_valid; |
|
wire [31:0] w_e_opcode; |
|
// Register writeback value |
wire [4:0] w_wb_rd; |
wire [31:0] w_wb_reg_rd; |
|
// Register writeback enable |
wire w_wb_write_rd; |
|
// Result from execute |
wire [31:0] w_e_result; |
wire w_e_mult; |
wire [31:0] w_e_mult_result; |
|
// Branch request |
wire w_e_branch; |
wire [31:0] w_e_branch_pc; |
wire w_e_stall; |
|
wire icache_rd; |
wire [31:0] icache_pc; |
wire [31:0] icache_inst; |
wire icache_miss; |
wire icache_valid; |
wire icache_busy; |
wire icache_invalidate; |
|
wire [31:0] dcache_addr; |
wire [31:0] dcache_data_o; |
wire [31:0] dcache_data_i; |
wire [3:0] dcache_wr; |
wire dcache_rd; |
wire dcache_ack; |
wire dcache_accept; |
wire dcache_flush; |
|
//----------------------------------------------------------------- |
// Instantiation |
//----------------------------------------------------------------- |
|
// Instruction Cache |
generate |
if (ENABLE_ICACHE == "ENABLED") |
begin : ICACHE |
// Instruction cache |
altor32_icache |
#( |
.BOOT_VECTOR(BOOT_VECTOR) |
) |
u_icache |
( |
.clk_i(clk_i), |
.rst_i(rst_i), |
|
// Processor interface |
.rd_i(icache_rd), |
.pc_i(icache_pc), |
.instruction_o(icache_inst), |
.valid_o(icache_valid), |
.invalidate_i(icache_invalidate), |
|
// Status |
.miss_o(icache_miss), |
.busy_o(icache_busy), |
|
// Instruction memory |
.mem_addr_o(imem_addr_o), |
.mem_data_i(imem_data_in_i), |
.mem_burst_o(imem_burst_o), |
.mem_rd_o(imem_rd_o), |
.mem_accept_i(imem_accept_i), |
.mem_ack_i(imem_ack_i) |
); |
end |
else |
begin |
// No instruction cache |
altor32_noicache |
u_icache |
( |
.clk_i(clk_i), |
.rst_i(rst_i), |
|
// Processor interface |
.rd_i(icache_rd), |
.pc_i(icache_pc), |
.instruction_o(icache_inst), |
.valid_o(icache_valid), |
|
// Instruction memory |
.mem_addr_o(imem_addr_o), |
.mem_data_i(imem_data_in_i), |
.mem_burst_o(imem_burst_o), |
.mem_rd_o(imem_rd_o), |
.mem_accept_i(imem_accept_i), |
.mem_ack_i(imem_ack_i) |
); |
end |
endgenerate |
|
// Instruction Fetch |
altor32_fetch |
#( |
.BOOT_VECTOR(BOOT_VECTOR) |
) |
u_fetch |
( |
// General |
.clk_i(clk_i), |
.rst_i(rst_i), |
|
// Instruction memory |
.pc_o(icache_pc), |
.data_i(icache_inst), |
.fetch_o(icache_rd), |
.data_valid_i(icache_valid), |
|
// Fetched opcode |
.opcode_o(w_d_opcode), |
.opcode_pc_o(w_d_pc), |
.opcode_valid_o(w_d_valid), |
|
// Branch target |
.branch_i(w_e_branch), |
.branch_pc_i(w_e_branch_pc), |
.stall_i(w_e_stall), |
|
// Decoded register details |
.ra_o(w_ra), |
.rb_o(w_rb), |
.rd_o(w_rd) |
); |
|
// Register file |
generate |
if (REGISTER_FILE_TYPE == "XILINX") |
begin |
altor32_regfile_xil |
#( |
.SUPPORT_32REGS(SUPPORT_32REGS) |
) |
reg_bank |
( |
// Clocking |
.clk_i(clk_i), |
.rst_i(rst_i), |
.wr_i(w_wb_write_rd), |
|
// Tri-port |
.rs_i(w_ra), |
.rt_i(w_rb), |
.rd_i(w_wb_rd), |
.reg_rs_o(w_reg_ra), |
.reg_rt_o(w_reg_rb), |
.reg_rd_i(w_wb_reg_rd) |
); |
end |
else if (REGISTER_FILE_TYPE == "ALTERA") |
begin |
altor32_regfile_alt |
#( |
.SUPPORT_32REGS(SUPPORT_32REGS) |
) |
reg_bank |
( |
// Clocking |
.clk_i(clk_i), |
.rst_i(rst_i), |
.wr_i(w_wb_write_rd), |
|
// Tri-port |
.rs_i(w_ra), |
.rt_i(w_rb), |
.rd_i(w_wb_rd), |
.reg_rs_o(w_reg_ra), |
.reg_rt_o(w_reg_rb), |
.reg_rd_i(w_wb_reg_rd) |
); |
end |
else |
begin |
altor32_regfile_sim |
#( |
.SUPPORT_32REGS(SUPPORT_32REGS) |
) |
reg_bank |
( |
// Clocking |
.clk_i(clk_i), |
.rst_i(rst_i), |
.wr_i(w_wb_write_rd), |
|
// Tri-port |
.rs_i(w_ra), |
.rt_i(w_rb), |
.rd_i(w_wb_rd), |
.reg_rs_o(w_reg_ra), |
.reg_rt_o(w_reg_rb), |
.reg_rd_i(w_wb_reg_rd) |
); |
end |
endgenerate |
|
generate |
if (ENABLE_DCACHE == "ENABLED") |
begin |
// Data cache |
altor32_dcache |
u_dcache |
( |
.clk_i(clk_i), |
.rst_i(rst_i), |
|
.flush_i(dcache_flush), |
|
// Processor interface |
.address_i({dcache_addr[31:2], 2'b00}), |
.data_o(dcache_data_i), |
.data_i(dcache_data_o), |
.wr_i(dcache_wr), |
.rd_i(dcache_rd), |
.accept_o(dcache_accept), |
.ack_o(dcache_ack), |
|
// Memory interface (slave) |
.mem_addr_o(dmem_addr_o), |
.mem_data_i(dmem_data_in_i), |
.mem_data_o(dmem_data_out_o), |
.mem_burst_o(dmem_burst_o), |
.mem_rd_o(dmem_rd_o), |
.mem_wr_o(dmem_wr_o), |
.mem_accept_i(dmem_accept_i), |
.mem_ack_i(dmem_ack_i) |
); |
end |
else |
begin |
|
// No data cache |
assign dmem_addr_o = {dcache_addr[31:2], 2'b00}; |
assign dmem_data_out_o = dcache_data_o; |
assign dcache_data_i = dmem_data_in_i; |
assign dmem_rd_o = dcache_rd; |
assign dmem_wr_o = dcache_wr; |
assign dmem_burst_o = 1'b0; |
assign dcache_ack = dmem_ack_i; |
assign dcache_accept = dmem_accept_i; |
end |
endgenerate |
|
// Execution unit |
altor32_exec |
#( |
.BOOT_VECTOR(BOOT_VECTOR), |
.ISR_VECTOR(ISR_VECTOR) |
) |
u_exec |
( |
// General |
.clk_i(clk_i), |
.rst_i(rst_i), |
|
.intr_i(intr_i), |
.nmi_i(nmi_i), |
|
// Status |
.fault_o(fault_o), |
.break_o(break_o), |
|
// Cache control |
.icache_flush_o(icache_invalidate), |
.dcache_flush_o(dcache_flush), |
|
// Branch target |
.branch_o(w_e_branch), |
.branch_pc_o(w_e_branch_pc), |
.stall_o(w_e_stall), |
|
// Opcode & arguments |
.opcode_i(w_d_opcode), |
.opcode_pc_i(w_d_pc), |
.opcode_valid_i(w_d_valid), |
|
.reg_ra_i(w_ra), |
.reg_ra_value_i(w_reg_ra), |
|
.reg_rb_i(w_rb), |
.reg_rb_value_i(w_reg_rb), |
|
.reg_rd_i(w_rd), |
|
// Output |
.opcode_o(w_e_opcode), |
.reg_rd_o(w_e_rd), |
.reg_rd_value_o(w_e_result), |
.mult_o(w_e_mult), |
.mult_res_o(w_e_mult_result), |
|
// Register write back bypass |
.wb_rd_i(w_wb_rd), |
.wb_rd_value_i(w_wb_reg_rd), |
|
// Memory Interface |
.dmem_addr_o(dcache_addr), |
.dmem_data_out_o(dcache_data_o), |
.dmem_data_in_i(dcache_data_i), |
.dmem_wr_o(dcache_wr), |
.dmem_rd_o(dcache_rd), |
.dmem_accept_i(dcache_accept), |
.dmem_ack_i(dcache_ack) |
); |
|
// Register file writeback |
altor32_writeback |
u_wb |
( |
// General |
.clk_i(clk_i), |
.rst_i(rst_i), |
|
// Opcode |
.opcode_i(w_e_opcode), |
|
// Register target |
.rd_i(w_e_rd), |
|
// ALU result |
.alu_result_i(w_e_result), |
|
// Memory load result |
.mem_result_i(dcache_data_i), |
.mem_offset_i(dcache_addr[1:0]), |
.mem_ready_i(dcache_ack), |
|
// Multiplier result |
.mult_i(w_e_mult), |
.mult_result_i(w_e_mult_result), |
|
// Outputs |
.write_enable_o(w_wb_write_rd), |
.write_addr_o(w_wb_rd), |
.write_data_o(w_wb_reg_rd) |
); |
|
//------------------------------------------------------------------- |
// Hooks for debug |
//------------------------------------------------------------------- |
`ifdef verilator |
function [31:0] get_pc; |
// verilator public |
get_pc = w_d_pc; |
endfunction |
function get_fault; |
// verilator public |
get_fault = fault_o; |
endfunction |
function get_break; |
// verilator public |
get_break = break_o; |
endfunction |
`endif |
|
endmodule |
/rtl/cpu/altor32_alu.v
0,0 → 1,209
//----------------------------------------------------------------- |
// AltOR32 |
// Alternative Lightweight OpenRisc |
// V2.0 |
// Ultra-Embedded.com |
// Copyright 2011 - 2013 |
// |
// Email: admin@ultra-embedded.com |
// |
// License: LGPL |
//----------------------------------------------------------------- |
// |
// Copyright (C) 2011 - 2013 Ultra-Embedded.com |
// |
// This source file may be used and distributed without |
// restriction provided that this copyright statement is not |
// removed from the file and that any derivative work contains |
// the original copyright notice and the associated disclaimer. |
// |
// This source file is free software; you can redistribute it |
// and/or modify it under the terms of the GNU Lesser General |
// Public License as published by the Free Software Foundation; |
// either version 2.1 of the License, or (at your option) any |
// later version. |
// |
// This source is distributed in the hope that it will be |
// useful, but WITHOUT ANY WARRANTY; without even the implied |
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR |
// PURPOSE. See the GNU Lesser General Public License for more |
// details. |
// |
// You should have received a copy of the GNU Lesser General |
// Public License along with this source; if not, write to the |
// Free Software Foundation, Inc., 59 Temple Place, Suite 330, |
// Boston, MA 02111-1307 USA |
//----------------------------------------------------------------- |
|
//----------------------------------------------------------------- |
// Includes |
//----------------------------------------------------------------- |
`include "altor32_defs.v" |
|
//----------------------------------------------------------------- |
// Module - ALU |
//----------------------------------------------------------------- |
module altor32_alu |
( |
// ALU operation select |
input [3:0] op_i /*verilator public*/, |
|
// Operands |
input [31:0] a_i /*verilator public*/, |
input [31:0] b_i /*verilator public*/, |
input c_i /*verilator public*/, |
|
// Result |
output [31:0] p_o /*verilator public*/, |
|
// Carry |
output reg c_o /*verilator public*/, |
output reg c_update_o /*verilator public*/ |
); |
|
//----------------------------------------------------------------- |
// Registers |
//----------------------------------------------------------------- |
reg [31:0] result; |
|
reg [31:16] shift_right_fill; |
reg [31:0] shift_right_1; |
reg [31:0] shift_right_2; |
reg [31:0] shift_right_4; |
reg [31:0] shift_right_8; |
|
reg [31:0] shift_left_1; |
reg [31:0] shift_left_2; |
reg [31:0] shift_left_4; |
reg [31:0] shift_left_8; |
|
//----------------------------------------------------------------- |
// ALU |
//----------------------------------------------------------------- |
always @ (op_i or a_i or b_i or c_i) |
begin |
case (op_i) |
//---------------------------------------------- |
// Shift Left |
//---------------------------------------------- |
`ALU_SHIFTL : |
begin |
if (b_i[0] == 1'b1) |
shift_left_1 = {a_i[30:0],1'b0}; |
else |
shift_left_1 = a_i; |
|
if (b_i[1] == 1'b1) |
shift_left_2 = {shift_left_1[29:0],2'b00}; |
else |
shift_left_2 = shift_left_1; |
|
if (b_i[2] == 1'b1) |
shift_left_4 = {shift_left_2[27:0],4'b0000}; |
else |
shift_left_4 = shift_left_2; |
|
if (b_i[3] == 1'b1) |
shift_left_8 = {shift_left_4[23:0],8'b00000000}; |
else |
shift_left_8 = shift_left_4; |
|
if (b_i[4] == 1'b1) |
result = {shift_left_8[15:0],16'b0000000000000000}; |
else |
result = shift_left_8; |
|
c_o = 1'b0; |
c_update_o = 1'b0; |
end |
//---------------------------------------------- |
// Shift Right |
//---------------------------------------------- |
`ALU_SHIFTR, `ALU_SHIRTR_ARITH: |
begin |
// Arithmetic shift? Fill with 1's if MSB set |
if (a_i[31] == 1'b1 && op_i == `ALU_SHIRTR_ARITH) |
shift_right_fill = 16'b1111111111111111; |
else |
shift_right_fill = 16'b0000000000000000; |
|
if (b_i[0] == 1'b1) |
shift_right_1 = {shift_right_fill[31], a_i[31:1]}; |
else |
shift_right_1 = a_i; |
|
if (b_i[1] == 1'b1) |
shift_right_2 = {shift_right_fill[31:30], shift_right_1[31:2]}; |
else |
shift_right_2 = shift_right_1; |
|
if (b_i[2] == 1'b1) |
shift_right_4 = {shift_right_fill[31:28], shift_right_2[31:4]}; |
else |
shift_right_4 = shift_right_2; |
|
if (b_i[3] == 1'b1) |
shift_right_8 = {shift_right_fill[31:24], shift_right_4[31:8]}; |
else |
shift_right_8 = shift_right_4; |
|
if (b_i[4] == 1'b1) |
result = {shift_right_fill[31:16], shift_right_8[31:16]}; |
else |
result = shift_right_8; |
|
c_o = 1'b0; |
c_update_o = 1'b0; |
end |
//---------------------------------------------- |
// Arithmetic |
//---------------------------------------------- |
`ALU_ADD : |
begin |
{c_o, result} = (a_i + b_i); |
c_update_o = 1'b1; |
end |
`ALU_ADDC : |
begin |
{c_o, result} = (a_i + b_i) + {31'h00000000, c_i}; |
c_update_o = 1'b1; |
end |
`ALU_SUB : |
begin |
result = (a_i - b_i); |
c_o = 1'b0; |
c_update_o = 1'b0; |
end |
//---------------------------------------------- |
// Logical |
//---------------------------------------------- |
`ALU_AND : |
begin |
result = (a_i & b_i); |
c_o = 1'b0; |
c_update_o = 1'b0; |
end |
`ALU_OR : |
begin |
result = (a_i | b_i); |
c_o = 1'b0; |
c_update_o = 1'b0; |
end |
`ALU_XOR : |
begin |
result = (a_i ^ b_i); |
c_o = 1'b0; |
c_update_o = 1'b0; |
end |
default : |
begin |
result = a_i; |
c_o = 1'b0; |
c_update_o = 1'b0; |
end |
endcase |
end |
|
assign p_o = result; |
|
endmodule |
/rtl/cpu/altor32_ram_sp.v
0,0 → 1,77
//----------------------------------------------------------------- |
// AltOR32 |
// Alternative Lightweight OpenRisc |
// V2.0 |
// Ultra-Embedded.com |
// Copyright 2011 - 2013 |
// |
// Email: admin@ultra-embedded.com |
// |
// License: LGPL |
//----------------------------------------------------------------- |
// |
// Copyright (C) 2011 - 2013 Ultra-Embedded.com |
// |
// This source file may be used and distributed without |
// restriction provided that this copyright statement is not |
// removed from the file and that any derivative work contains |
// the original copyright notice and the associated disclaimer. |
// |
// This source file is free software; you can redistribute it |
// and/or modify it under the terms of the GNU Lesser General |
// Public License as published by the Free Software Foundation; |
// either version 2.1 of the License, or (at your option) any |
// later version. |
// |
// This source is distributed in the hope that it will be |
// useful, but WITHOUT ANY WARRANTY; without even the implied |
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR |
// PURPOSE. See the GNU Lesser General Public License for more |
// details. |
// |
// You should have received a copy of the GNU Lesser General |
// Public License along with this source; if not, write to the |
// Free Software Foundation, Inc., 59 Temple Place, Suite 330, |
// Boston, MA 02111-1307 USA |
//----------------------------------------------------------------- |
|
//----------------------------------------------------------------- |
// Module: altor32_ram_sp - Single port RAM (used in cache) |
//----------------------------------------------------------------- |
module altor32_ram_sp |
( |
input clk_i /*verilator public*/, |
output [(WIDTH - 1):0] dat_o /*verilator public*/, |
input [(WIDTH - 1):0] dat_i /*verilator public*/, |
input [(SIZE - 1):0] adr_i /*verilator public*/, |
input wr_i /*verilator public*/ |
); |
|
//----------------------------------------------------------------- |
// Params |
//----------------------------------------------------------------- |
parameter [31:0] WIDTH = 8; |
parameter [31:0] SIZE = 14; |
|
//----------------------------------------------------------------- |
// Registers |
//----------------------------------------------------------------- |
reg [(WIDTH - 1):0] ram [((2<< (SIZE-1)) - 1):0] /*verilator public*/; |
reg [(SIZE - 1):0] rd_addr; |
|
//----------------------------------------------------------------- |
// Processes |
//----------------------------------------------------------------- |
always @ (posedge clk_i) |
begin |
if (wr_i == 1'b1) |
ram[adr_i] <= dat_i; |
rd_addr <= adr_i; |
end |
|
//------------------------------------------------------------------- |
// Combinatorial |
//------------------------------------------------------------------- |
assign dat_o = ram[rd_addr]; |
|
endmodule |
/rtl/cpu/altor32_defs.v
0,0 → 1,185
//----------------------------------------------------------------- |
// AltOR32 |
// Alternative Lightweight OpenRisc |
// V2.0 |
// Ultra-Embedded.com |
// Copyright 2011 - 2013 |
// |
// Email: admin@ultra-embedded.com |
// |
// License: LGPL |
//----------------------------------------------------------------- |
// |
// Copyright (C) 2011 - 2013 Ultra-Embedded.com |
// |
// This source file may be used and distributed without |
// restriction provided that this copyright statement is not |
// removed from the file and that any derivative work contains |
// the original copyright notice and the associated disclaimer. |
// |
// This source file is free software; you can redistribute it |
// and/or modify it under the terms of the GNU Lesser General |
// Public License as published by the Free Software Foundation; |
// either version 2.1 of the License, or (at your option) any |
// later version. |
// |
// This source is distributed in the hope that it will be |
// useful, but WITHOUT ANY WARRANTY; without even the implied |
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR |
// PURPOSE. See the GNU Lesser General Public License for more |
// details. |
// |
// You should have received a copy of the GNU Lesser General |
// Public License along with this source; if not, write to the |
// Free Software Foundation, Inc., 59 Temple Place, Suite 330, |
// Boston, MA 02111-1307 USA |
//----------------------------------------------------------------- |
|
//----------------------------------------------------------------- |
// ALU Operations |
//----------------------------------------------------------------- |
`define ALU_NONE 4'b0000 |
`define ALU_SHIFTL 4'b0001 |
`define ALU_SHIFTR 4'b0010 |
`define ALU_SHIRTR_ARITH 4'b0011 |
`define ALU_ADD 4'b0100 |
`define ALU_ADDC 4'b0101 |
`define ALU_SUB 4'b0110 |
`define ALU_AND 4'b0111 |
`define ALU_OR 4'b1000 |
`define ALU_XOR 4'b1001 |
|
//----------------------------------------------------------------- |
// ALU Instructions |
//----------------------------------------------------------------- |
`define INST_OR32_ALU 8'h38 |
`define INST_OR32_ADD 8'h00 |
`define INST_OR32_ADDC 8'h01 |
`define INST_OR32_AND 8'h03 |
`define INST_OR32_OR 8'h04 |
`define INST_OR32_SLL 8'h08 |
`define INST_OR32_SRA 8'h28 |
`define INST_OR32_SRL 8'h18 |
`define INST_OR32_SUB 8'h02 |
`define INST_OR32_XOR 8'h05 |
`define INST_OR32_MUL 8'hc6 |
`define INST_OR32_MULU 8'hcb |
|
//----------------------------------------------------------------- |
// INST_OR32_SHIFTI Instructions |
//----------------------------------------------------------------- |
`define INST_OR32_SHIFTI 8'h2E |
`define INST_OR32_SLLI 2'b00 |
`define INST_OR32_SRAI 2'b10 |
`define INST_OR32_SRLI 2'b01 |
|
//----------------------------------------------------------------- |
// General Instructions |
//----------------------------------------------------------------- |
`define INST_OR32_ADDI 8'h27 |
`define INST_OR32_ANDI 8'h29 |
`define INST_OR32_BF 8'h04 |
`define INST_OR32_BNF 8'h03 |
`define INST_OR32_J 8'h00 |
`define INST_OR32_JAL 8'h01 |
`define INST_OR32_JALR 8'h12 |
`define INST_OR32_JR 8'h11 |
`define INST_OR32_MFSPR 8'h2D |
`define INST_OR32_MOVHI 8'h06 |
`define INST_OR32_MTSPR 8'h30 |
`define INST_OR32_NOP 8'h05 |
`define INST_OR32_ORI 8'h2A |
`define INST_OR32_RFE 8'h09 |
`define INST_OR32_SB 8'h36 |
`define INST_OR32_SH 8'h37 |
`define INST_OR32_SW 8'h35 |
`define INST_OR32_XORI 8'h2B |
`define INST_OR32_LBS 8'h24 |
`define INST_OR32_LBZ 8'h23 |
`define INST_OR32_LHS 8'h26 |
`define INST_OR32_LHZ 8'h25 |
`define INST_OR32_LWZ 8'h21 |
`define INST_OR32_LWS 8'h22 |
|
//----------------------------------------------------------------- |
// Set Flag Instructions |
//----------------------------------------------------------------- |
`define INST_OR32_SFXX 8'h2F |
`define INST_OR32_SFXXI 8'h39 |
`define INST_OR32_SFEQ 16'h0720 |
`define INST_OR32_SFEQI 16'h05E0 |
`define INST_OR32_SFGES 16'h072B |
`define INST_OR32_SFGESI 16'h05EB |
`define INST_OR32_SFGEU 16'h0723 |
`define INST_OR32_SFGEUI 16'h05E3 |
`define INST_OR32_SFGTS 16'h072A |
`define INST_OR32_SFGTSI 16'h05EA |
`define INST_OR32_SFGTU 16'h0722 |
`define INST_OR32_SFGTUI 16'h05E2 |
`define INST_OR32_SFLES 16'h072D |
`define INST_OR32_SFLESI 16'h05ED |
`define INST_OR32_SFLEU 16'h0725 |
`define INST_OR32_SFLEUI 16'h05E5 |
`define INST_OR32_SFLTS 16'h072C |
`define INST_OR32_SFLTSI 16'h05EC |
`define INST_OR32_SFLTU 16'h0724 |
`define INST_OR32_SFLTUI 16'h05E4 |
`define INST_OR32_SFNE 16'h0721 |
`define INST_OR32_SFNEI 16'h05E1 |
|
//----------------------------------------------------------------- |
// Misc Instructions |
//----------------------------------------------------------------- |
`define INST_OR32_MISC 8'h08 |
`define INST_OR32_SYS 8'h20 |
`define INST_OR32_TRAP 8'h21 |
|
`define INST_OR32_BUBBLE 8'h3F |
`define OPCODE_INST_BUBBLE 32'hFC000000 |
|
//----------------------------------------------------------------- |
// SPR Register Map |
//----------------------------------------------------------------- |
`define SPR_REG_VR 16'h0000 |
`define SPR_VERSION_CURRENT 8'h00 |
`define SPR_REG_SR 16'h0011 |
`define SPR_REG_EPCR 16'h0020 |
`define SPR_REG_ESR 16'h0040 |
|
`define SPR_REG_MACLO 16'h0080 |
`define SPR_REG_MACHI 16'h0081 |
|
//----------------------------------------------------------------- |
// SR Register bits |
//----------------------------------------------------------------- |
`define OR32_SR_SM 0 |
`define OR32_SR_TEE 1 |
`define OR32_SR_IEE 2 |
`define OR32_SR_DCE 3 |
`define OR32_SR_ICE 4 |
`define OR32_SR_DME 5 |
`define OR32_SR_IME 6 |
`define OR32_SR_LEE 7 |
`define OR32_SR_CE 8 |
`define OR32_SR_F 9 |
`define OR32_SR_CY 10 |
`define OR32_SR_OV 11 |
`define OR32_SR_OVE 12 |
`define OR32_SR_DSX 13 |
`define OR32_SR_EPH 14 |
`define OR32_SR_FO 15 |
`define OR32_SR_TED 16 |
`define OR32_SR_ICACHE_FLUSH 17 |
`define OR32_SR_DCACHE_FLUSH 18 |
|
//----------------------------------------------------------------- |
// OR32 Vectors |
// NOTE: These differ from the real OR32 vectors for space reasons |
//----------------------------------------------------------------- |
`define VECTOR_RESET 32'h00000100 |
`define VECTOR_ILLEGAL_INST 32'h00000200 |
`define VECTOR_EXTINT 32'h00000300 |
`define VECTOR_SYSCALL 32'h00000400 |
`define VECTOR_TRAP 32'h00000600 |
`define VECTOR_NMI 32'h00000700 |
`define VECTOR_BUS_ERROR 32'h00000800 |
/rtl/cpu/altor32_dcache_mem_if.v
0,0 → 1,311
//----------------------------------------------------------------- |
// AltOR32 |
// Alternative Lightweight OpenRisc |
// V2.0 |
// Ultra-Embedded.com |
// Copyright 2011 - 2013 |
// |
// Email: admin@ultra-embedded.com |
// |
// License: LGPL |
//----------------------------------------------------------------- |
// |
// Copyright (C) 2011 - 2013 Ultra-Embedded.com |
// |
// This source file may be used and distributed without |
// restriction provided that this copyright statement is not |
// removed from the file and that any derivative work contains |
// the original copyright notice and the associated disclaimer. |
// |
// This source file is free software; you can redistribute it |
// and/or modify it under the terms of the GNU Lesser General |
// Public License as published by the Free Software Foundation; |
// either version 2.1 of the License, or (at your option) any |
// later version. |
// |
// This source is distributed in the hope that it will be |
// useful, but WITHOUT ANY WARRANTY; without even the implied |
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR |
// PURPOSE. See the GNU Lesser General Public License for more |
// details. |
// |
// You should have received a copy of the GNU Lesser General |
// Public License along with this source; if not, write to the |
// Free Software Foundation, Inc., 59 Temple Place, Suite 330, |
// Boston, MA 02111-1307 USA |
//----------------------------------------------------------------- |
|
//----------------------------------------------------------------- |
// Module - Data Cache Memory Interface |
//----------------------------------------------------------------- |
module altor32_dcache_mem_if |
( |
input clk_i /*verilator public*/, |
input rst_i /*verilator public*/, |
|
// Cache interface |
input [31:0] address_i /*verilator public*/, |
input [31:0] data_i /*verilator public*/, |
output [31:0] data_o /*verilator public*/, |
input fill_i /*verilator public*/, |
input evict_i /*verilator public*/, |
input [31:0] evict_addr_i /*verilator public*/, |
input rd_single_i /*verilator public*/, |
input [3:0] wr_single_i /*verilator public*/, |
output done_o /*verilator public*/, |
|
// Cache memory (fill/evict) |
output [31:2] cache_addr_o /*verilator public*/, |
output [31:0] cache_data_o /*verilator public*/, |
input [31:0] cache_data_i /*verilator public*/, |
output cache_wr_o /*verilator public*/, |
|
// Memory interface (slave) |
output [31:0] mem_addr_o /*verilator public*/, |
input [31:0] mem_data_i /*verilator public*/, |
output [31:0] mem_data_o /*verilator public*/, |
output mem_burst_o /*verilator public*/, |
output mem_rd_o /*verilator public*/, |
output [3:0] mem_wr_o /*verilator public*/, |
input mem_accept_i/*verilator public*/, |
input mem_ack_i/*verilator public*/ |
); |
|
//----------------------------------------------------------------- |
// Params |
//----------------------------------------------------------------- |
parameter CACHE_LINE_SIZE_WIDTH = 5; /* 5-bits -> 32 entries */ |
parameter CACHE_LINE_WORDS_IDX_MAX = CACHE_LINE_SIZE_WIDTH - 2; /* 3-bit -> 8 words */ |
|
//----------------------------------------------------------------- |
// Registers / Wires |
//----------------------------------------------------------------- |
|
reg [31:2] cache_addr_o; |
reg [31:0] cache_data_o; |
reg cache_wr_o; |
|
reg [31:CACHE_LINE_SIZE_WIDTH] line_address; |
reg [CACHE_LINE_SIZE_WIDTH-3:0] line_word; |
|
reg [31:0] data_o; |
reg done_o; |
|
reg [31:0] mem_addr_o; |
reg [31:0] mem_data_o; |
reg mem_rd_o; |
reg [3:0] mem_wr_o; |
reg mem_burst_o; |
|
// Current state |
parameter STATE_IDLE = 0; |
parameter STATE_FETCH = 1; |
parameter STATE_READ_WAIT = 2; |
parameter STATE_WRITE = 3; |
parameter STATE_WRITE_WAIT = 4; |
parameter STATE_READ_SINGLE = 5; |
parameter STATE_WRITE_SINGLE= 6; |
|
reg [3:0] state; |
|
//----------------------------------------------------------------- |
// Control logic |
//----------------------------------------------------------------- |
reg [CACHE_LINE_SIZE_WIDTH-3:0] v_line_word; |
|
always @ (posedge rst_i or posedge clk_i ) |
begin |
if (rst_i == 1'b1) |
begin |
line_address <= {32-CACHE_LINE_SIZE_WIDTH{1'b0}}; |
line_word <= {CACHE_LINE_SIZE_WIDTH-2{1'b0}}; |
mem_addr_o <= 32'h00000000; |
mem_data_o <= 32'h00000000; |
mem_wr_o <= 4'h0; |
mem_rd_o <= 1'b0; |
mem_burst_o <= 1'b0; |
cache_addr_o <= 30'h00000000; |
cache_data_o <= 32'h00000000; |
cache_wr_o <= 1'b0; |
done_o <= 1'b0; |
data_o <= 32'h00000000; |
state <= STATE_IDLE; |
end |
else |
begin |
|
if (mem_accept_i) |
begin |
mem_rd_o <= 1'b0; |
mem_wr_o <= 4'h0; |
end |
|
done_o <= 1'b0; |
cache_wr_o <= 1'b0; |
|
case (state) |
|
//----------------------------------------- |
// IDLE |
//----------------------------------------- |
STATE_IDLE : |
begin |
// Perform cache evict (write) |
if (evict_i) |
begin |
line_address <= evict_addr_i[31:CACHE_LINE_SIZE_WIDTH]; |
line_word <= {CACHE_LINE_SIZE_WIDTH-2{1'b0}}; |
|
// Read data from cache |
cache_addr_o <= {evict_addr_i[31:CACHE_LINE_SIZE_WIDTH], {CACHE_LINE_SIZE_WIDTH-2{1'b0}}}; |
state <= STATE_READ_WAIT; |
end |
// Perform cache fill (read) |
else if (fill_i) |
begin |
line_address <= address_i[31:CACHE_LINE_SIZE_WIDTH]; |
line_word <= {CACHE_LINE_SIZE_WIDTH-2{1'b0}}; |
|
// Start fetch from memory |
mem_addr_o <= {address_i[31:CACHE_LINE_SIZE_WIDTH], {CACHE_LINE_SIZE_WIDTH{1'b0}}}; |
mem_rd_o <= 1'b1; |
mem_burst_o <= 1'b1; |
state <= STATE_FETCH; |
end |
// Read single |
else if (rd_single_i) |
begin |
// Start fetch from memory |
mem_addr_o <= address_i; |
mem_data_o <= 32'b0; |
mem_rd_o <= 1'b1; |
mem_burst_o <= 1'b0; |
state <= STATE_READ_SINGLE; |
end |
// Write single |
else if (|wr_single_i) |
begin |
// Start fetch from memory |
mem_addr_o <= address_i; |
mem_data_o <= data_i; |
mem_wr_o <= wr_single_i; |
mem_burst_o <= 1'b0; |
state <= STATE_WRITE_SINGLE; |
end |
end |
//----------------------------------------- |
// FETCH - Fetch line from memory |
//----------------------------------------- |
STATE_FETCH : |
begin |
// Data ready from memory? |
if (mem_ack_i && mem_rd_o == 1'b0) |
begin |
// Write data into cache |
cache_addr_o <= {line_address, line_word}; |
cache_data_o <= mem_data_i; |
cache_wr_o <= 1'b1; |
|
// Line fetch complete? |
if (line_word == {CACHE_LINE_WORDS_IDX_MAX{1'b1}}) |
begin |
done_o <= 1'b1; |
state <= STATE_IDLE; |
end |
// Fetch next word for line |
else |
begin |
v_line_word = line_word + 1'b1; |
line_word <= v_line_word; |
|
mem_addr_o <= {line_address, v_line_word, 2'b00}; |
mem_rd_o <= 1'b1; |
|
if (line_word == ({CACHE_LINE_WORDS_IDX_MAX{1'b1}}-1)) |
begin |
mem_burst_o <= 1'b0; |
end |
end |
end |
end |
//----------------------------------------- |
// READ_WAIT - Wait for data from cache |
//----------------------------------------- |
STATE_READ_WAIT : |
begin |
// Not used yet, but set for start of burst |
mem_burst_o <= 1'b1; |
state <= STATE_WRITE; |
end |
//----------------------------------------- |
// WRITE - Write word to memory |
//----------------------------------------- |
STATE_WRITE : |
begin |
// Write data into memory from cache |
mem_addr_o <= {line_address, line_word, 2'b00}; |
mem_data_o <= cache_data_i; |
mem_wr_o <= 4'b1111; |
|
// Setup next word read from cache |
v_line_word = line_word + 1'b1; |
cache_addr_o <= {line_address, v_line_word}; |
|
state <= STATE_WRITE_WAIT; |
end |
//----------------------------------------- |
// WRITE_WAIT - Wait for write to complete |
//----------------------------------------- |
STATE_WRITE_WAIT: |
begin |
// Write to memory complete |
if (mem_ack_i && mem_wr_o == 4'b0) |
begin |
// Line write complete? |
if (line_word == {CACHE_LINE_WORDS_IDX_MAX{1'b1}}) |
begin |
done_o <= 1'b1; |
state <= STATE_IDLE; |
end |
// Fetch next word for line |
else |
begin |
line_word <= line_word + 1'b1; |
state <= STATE_WRITE; |
|
if (line_word == ({CACHE_LINE_WORDS_IDX_MAX{1'b1}}-1)) |
mem_burst_o <= 1'b0; |
end |
end |
end |
//----------------------------------------- |
// READ_SINGLE - Single access to memory |
//----------------------------------------- |
STATE_READ_SINGLE: |
begin |
// Data ready from memory? |
if (mem_ack_i && mem_rd_o == 1'b0) |
begin |
data_o <= mem_data_i; |
done_o <= 1'b1; |
state <= STATE_IDLE; |
end |
end |
//----------------------------------------- |
// WRITE_SINGLE - Single access to memory |
//----------------------------------------- |
STATE_WRITE_SINGLE: |
begin |
if (mem_ack_i && mem_wr_o == 4'b0) |
begin |
done_o <= 1'b1; |
state <= STATE_IDLE; |
end |
end |
default: |
; |
endcase |
end |
end |
|
endmodule |
/rtl/cpu/altor32_exec.v
0,0 → 1,1377
//----------------------------------------------------------------- |
// AltOR32 |
// Alternative Lightweight OpenRisc |
// V2.0 |
// Ultra-Embedded.com |
// Copyright 2011 - 2013 |
// |
// Email: admin@ultra-embedded.com |
// |
// License: LGPL |
//----------------------------------------------------------------- |
// |
// Copyright (C) 2011 - 2013 Ultra-Embedded.com |
// |
// This source file may be used and distributed without |
// restriction provided that this copyright statement is not |
// removed from the file and that any derivative work contains |
// the original copyright notice and the associated disclaimer. |
// |
// This source file is free software; you can redistribute it |
// and/or modify it under the terms of the GNU Lesser General |
// Public License as published by the Free Software Foundation; |
// either version 2.1 of the License, or (at your option) any |
// later version. |
// |
// This source is distributed in the hope that it will be |
// useful, but WITHOUT ANY WARRANTY; without even the implied |
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR |
// PURPOSE. See the GNU Lesser General Public License for more |
// details. |
// |
// You should have received a copy of the GNU Lesser General |
// Public License along with this source; if not, write to the |
// Free Software Foundation, Inc., 59 Temple Place, Suite 330, |
// Boston, MA 02111-1307 USA |
//----------------------------------------------------------------- |
|
//`define CONF_CORE_DEBUG |
//`define CONF_CORE_DEBUG_BUBBLE |
//`define CONF_CORE_TRACE |
//`define CONF_CORE_FAULT_ON_OPCODE0 |
|
//----------------------------------------------------------------- |
// Includes |
//----------------------------------------------------------------- |
`include "altor32_defs.v" |
|
//----------------------------------------------------------------- |
// Module - Instruction Execute |
//----------------------------------------------------------------- |
module altor32_exec |
( |
// General |
input clk_i /*verilator public*/, |
input rst_i /*verilator public*/, |
|
// Maskable interrupt |
input intr_i /*verilator public*/, |
|
// Unmaskable interrupt |
input nmi_i /*verilator public*/, |
|
// Fault |
output reg fault_o /*verilator public*/, |
|
// Breakpoint / Trap |
output reg break_o /*verilator public*/, |
|
// Cache control |
output reg icache_flush_o /*verilator public*/, |
output reg dcache_flush_o /*verilator public*/, |
|
// Branch |
output branch_o /*verilator public*/, |
output [31:0] branch_pc_o /*verilator public*/, |
output stall_o /*verilator public*/, |
|
// Opcode & arguments |
input [31:0] opcode_i /*verilator public*/, |
input [31:0] opcode_pc_i /*verilator public*/, |
input opcode_valid_i /*verilator public*/, |
|
// Reg A |
input [4:0] reg_ra_i /*verilator public*/, |
input [31:0] reg_ra_value_i /*verilator public*/, |
|
// Reg B |
input [4:0] reg_rb_i /*verilator public*/, |
input [31:0] reg_rb_value_i /*verilator public*/, |
|
// Reg D |
input [4:0] reg_rd_i /*verilator public*/, |
|
// Output |
output [31:0] opcode_o /*verilator public*/, |
output [4:0] reg_rd_o /*verilator public*/, |
output [31:0] reg_rd_value_o /*verilator public*/, |
output mult_o /*verilator public*/, |
output [31:0] mult_res_o /*verilator public*/, |
|
// Register write back bypass |
input [4:0] wb_rd_i /*verilator public*/, |
input [31:0] wb_rd_value_i /*verilator public*/, |
|
// Memory Interface |
output reg [31:0] dmem_addr_o /*verilator public*/, |
output reg [31:0] dmem_data_out_o /*verilator public*/, |
input [31:0] dmem_data_in_i /*verilator public*/, |
output reg [3:0] dmem_wr_o /*verilator public*/, |
output reg dmem_rd_o /*verilator public*/, |
input dmem_accept_i /*verilator public*/, |
input dmem_ack_i /*verilator public*/ |
); |
|
//----------------------------------------------------------------- |
// Params |
//----------------------------------------------------------------- |
parameter BOOT_VECTOR = 32'h00000000; |
parameter ISR_VECTOR = 32'h00000000; |
|
//----------------------------------------------------------------- |
// Registers |
//----------------------------------------------------------------- |
|
// Branch PC |
reg [31:0] r_pc_branch; |
reg r_pc_fetch; |
reg r_stall; |
|
// Exception saved program counter |
reg [31:0] r_epc; |
|
// Supervisor register |
reg [31:0] r_sr; |
|
// Exception saved supervisor register |
reg [31:0] r_esr; |
|
// Destination register number (post execute stage) |
reg [4:0] r_e_rd; |
|
// Current opcode (PC for debug) |
reg [31:0] r_e_opcode; |
reg [31:0] r_e_opcode_pc; |
|
// ALU input A |
reg [31:0] r_e_alu_a; |
|
// ALU input B |
reg [31:0] r_e_alu_b; |
|
// ALU output |
wire [31:0] r_e_result; |
|
// Resolved RA/RB register contents |
wire [31:0] ra_value_resolved; |
wire [31:0] rb_value_resolved; |
wire resolve_failed; |
|
// ALU Carry |
wire alu_carry_out; |
wire alu_carry_update; |
|
// ALU operation selection |
reg [3:0] r_e_alu_func; |
|
// Load instruction details |
reg [4:0] r_load_rd; |
reg [7:0] r_load_inst; |
reg [1:0] r_load_offset; |
|
// Load forwarding |
wire load_insn; |
wire [31:0] load_result; |
|
// Memory access? |
reg r_mem_load; |
reg r_mem_store; |
reg r_mem_access; |
|
wire load_pending; |
wire store_pending; |
wire load_insert; |
wire load_stall; |
|
reg d_mem_load; |
|
// Delayed NMI |
reg r_nmi; |
|
//----------------------------------------------------------------- |
// Instantiation |
//----------------------------------------------------------------- |
|
// ALU |
altor32_alu alu |
( |
// ALU operation select |
.op_i(r_e_alu_func), |
|
// Operands |
.a_i(r_e_alu_a), |
.b_i(r_e_alu_b), |
.c_i(r_sr[`OR32_SR_CY]), |
|
// Result |
.p_o(r_e_result), |
|
// Carry |
.c_o(alu_carry_out), |
.c_update_o(alu_carry_update) |
); |
|
// Load result forwarding |
altor32_lfu |
u_lfu |
( |
// Opcode |
.opcode_i(r_load_inst), |
|
// Memory load result |
.mem_result_i(dmem_data_in_i), |
.mem_offset_i(r_load_offset), |
|
// Result |
.load_result_o(load_result), |
.load_insn_o(load_insn) |
); |
|
// Load / store pending logic |
altor32_lsu |
u_lsu |
( |
// Current instruction |
.opcode_valid_i(opcode_valid_i & ~r_pc_fetch), |
.opcode_i({2'b00,opcode_i[31:26]}), |
|
// Load / Store pending |
.load_pending_i(r_mem_load), |
.store_pending_i(r_mem_store), |
|
// Load dest register |
.rd_load_i(r_load_rd), |
|
// Load insn in WB stage |
.load_wb_i(d_mem_load), |
|
// Memory status |
.mem_access_i(r_mem_access), |
.mem_ack_i(dmem_ack_i), |
|
// Load / store still pending |
.load_pending_o(load_pending), |
.store_pending_o(store_pending), |
|
// Insert load result into pipeline |
.write_result_o(load_insert), |
|
// Stall pipeline due |
.stall_o(load_stall) |
); |
|
// Operand forwarding |
altor32_dfu |
u_dfu |
( |
// Input registers |
.ra_i(reg_ra_i), |
.rb_i(reg_rb_i), |
|
// Input register contents |
.ra_regval_i(reg_ra_value_i), |
.rb_regval_i(reg_rb_value_i), |
|
// Dest register (EXEC stage) |
.rd_ex_i(r_e_rd), |
|
// Dest register (WB stage) |
.rd_wb_i(wb_rd_i), |
|
// Load pending / target |
.load_pending_i(load_pending), |
.rd_load_i(r_load_rd), |
|
// Multiplier status |
.mult_lo_ex_i(1'b0), |
.mult_hi_ex_i(1'b0), |
.mult_lo_wb_i(1'b0), |
.mult_hi_wb_i(1'b0), |
|
// Multiplier result |
.result_mult_i(64'b0), |
|
// Result (EXEC) |
.result_ex_i(r_e_result), |
|
// Result (WB) |
.result_wb_i(wb_rd_value_i), |
|
// Resolved register values |
.result_ra_o(ra_value_resolved), |
.result_rb_o(rb_value_resolved), |
|
// Stall due to failed resolve |
.stall_o(resolve_failed) |
); |
|
//------------------------------------------------------------------- |
// Execute: Execute opcode |
//------------------------------------------------------------------- |
|
// Execute stage blocking assignment vars |
reg [7:0] v_inst; |
reg [4:0] v_rd; |
reg [7:0] v_alu_op; |
reg [1:0] v_shift_op; |
reg [15:0] v_sfxx_op; |
reg [15:0] v_imm; |
reg [31:0] v_imm_uint32; |
reg [31:0] v_imm_int32; |
reg [31:0] v_store_imm; |
reg [15:0] v_mxspr_imm; |
reg [31:0] v_target; |
reg [31:0] v_reg_ra; |
reg [31:0] v_reg_rb; |
reg [31:0] v_pc; |
reg [31:0] v_offset; |
reg [31:0] v_shift_val; |
reg [31:0] v_shift_imm; |
reg [31:0] v_vector; |
reg [31:0] v_sr; |
reg [31:0] v_mem_addr; |
reg [31:0] v_mem_data_in; |
reg v_exception; |
reg v_branch; |
reg v_jmp; |
reg v_write_rd; |
reg v_store_pending; |
reg v_load_pending; |
reg v_inst_load; |
reg v_inst_store; |
reg v_stall; |
reg v_no_intr; |
reg v_opcode_valid; |
reg v_check_load_rd; |
|
always @ (posedge clk_i or posedge rst_i) |
begin |
if (rst_i == 1'b1) |
begin |
r_pc_branch <= 32'h00000000; |
r_pc_fetch <= 1'b0; |
r_stall <= 1'b0; |
|
// Status registers |
r_epc <= 32'h00000000; |
r_sr <= 32'h00000000; |
r_esr <= 32'h00000000; |
|
r_e_rd <= 5'b00000; |
|
// Default to no ALU operation |
r_e_alu_func <= `ALU_NONE; |
r_e_alu_a <= 32'h00000000; |
r_e_alu_b <= 32'h00000000; |
|
r_e_opcode <= 32'h00000000; |
r_e_opcode_pc <= 32'h00000000; |
|
// Data memory |
dmem_addr_o <= 32'h00000000; |
dmem_data_out_o <= 32'h00000000; |
dmem_rd_o <= 1'b0; |
dmem_wr_o <= 4'b0000; |
|
fault_o <= 1'b0; |
break_o <= 1'b0; |
|
r_nmi <= 1'b0; |
|
icache_flush_o <= 1'b0; |
dcache_flush_o <= 1'b0; |
|
r_mem_load <= 1'b0; |
r_mem_store <= 1'b0; |
r_mem_access <= 1'b0; |
|
r_load_rd <= 5'b00000; |
r_load_inst <= 8'h00; |
r_load_offset <= 2'b00; |
|
d_mem_load <= 1'b0; |
end |
else |
begin |
|
// If memory access accepted by slave |
if (dmem_accept_i) |
begin |
dmem_rd_o <= 1'b0; |
dmem_wr_o <= 4'b0000; |
end |
|
r_mem_access <= 1'b0; |
break_o <= 1'b0; |
icache_flush_o <= 1'b0; |
dcache_flush_o <= 1'b0; |
|
// Record NMI in-case it can't be processed this cycle |
if (nmi_i) |
r_nmi <= 1'b1; |
|
// Reset branch request |
r_pc_fetch <= 1'b0; |
|
v_exception = 1'b0; |
v_vector = 32'h00000000; |
v_branch = 1'b0; |
v_jmp = 1'b0; |
v_write_rd = 1'b0; |
v_sr = r_sr; |
v_stall = 1'b0; |
v_no_intr = 1'b0; |
|
d_mem_load <= r_mem_access & r_mem_load; |
|
//--------------------------------------------------------------- |
// Opcode |
//--------------------------------------------------------------- |
|
// Instruction not ready |
if (!opcode_valid_i) |
begin |
v_opcode_valid = 1'b0; |
|
`ifdef CONF_CORE_DEBUG_BUBBLE |
$display("%08x: Execute - Instruction not ready", opcode_pc_i); |
`endif |
end |
// Branch request, always drop the next instruction |
else if (r_pc_fetch) |
begin |
v_opcode_valid = 1'b0; |
|
`ifdef CONF_CORE_DEBUG |
$display("%08x: Exec - Branch pending, skip instruction (%x)", opcode_pc_i, opcode_i); |
`endif |
end |
// Valid instruction ready |
else |
begin |
v_mem_data_in = opcode_i; |
v_opcode_valid = 1'b1; |
|
`ifdef CONF_CORE_FAULT_ON_OPCODE0 |
// This is a valid opcode (branch to same instruction), |
// but rare and useful for catching pipeline errors |
if (v_mem_data_in == 32'h00000000) |
fault_o <= 1'b1; |
`endif |
end |
|
//--------------------------------------------------------------- |
// Decode opcode |
//--------------------------------------------------------------- |
v_alu_op = {v_mem_data_in[9:6],v_mem_data_in[3:0]}; |
v_sfxx_op = {5'b00,v_mem_data_in[31:21]}; |
v_shift_op = v_mem_data_in[7:6]; |
v_target = sign_extend_imm26(v_mem_data_in[25:0]); |
v_store_imm = sign_extend_imm16({v_mem_data_in[25:21],v_mem_data_in[10:0]}); |
|
// Signed & unsigned imm -> 32-bits |
v_imm = v_mem_data_in[15:0]; |
v_imm_int32 = sign_extend_imm16(v_imm); |
v_imm_uint32 = extend_imm16(v_imm); |
|
// Load register[ra] |
v_reg_ra = ra_value_resolved; |
|
// Load register[rb] |
v_reg_rb = rb_value_resolved; |
|
// Default to no ALU operation (output == input_a) |
r_e_alu_func <= `ALU_NONE; |
r_e_alu_a <= 32'h00000000; |
|
// Default target is R[d] |
v_rd = reg_rd_i; |
|
//--------------------------------------------------------------- |
// Outstanding memory access |
//--------------------------------------------------------------- |
|
// Pending accesses |
v_load_pending = load_pending; |
v_store_pending = store_pending; |
v_check_load_rd = 1'b1; |
|
// Stall pipeline due to load / store |
if (v_opcode_valid & load_stall) |
begin |
v_stall = 1'b1; |
v_opcode_valid = 1'b0; |
end |
|
// Insert load result into pipeline? |
if (load_insert) |
begin |
// Feed load result into pipeline |
r_e_alu_func <= `ALU_NONE; |
r_e_alu_a <= load_result; |
v_rd = r_load_rd; |
v_write_rd = 1'b1; |
end |
|
//--------------------------------------------------------------- |
// Invalid PC detection |
//--------------------------------------------------------------- |
|
// Detect incorrect program counter and cause FAULT |
if (opcode_valid_i && (opcode_pc_i[1:0] != 2'b00)) |
begin |
fault_o <= 1'b1; |
v_opcode_valid = 1'b0; |
v_exception = 1'b1; |
v_vector = ISR_VECTOR + `VECTOR_BUS_ERROR; |
end |
|
//--------------------------------------------------------------- |
// Failed operand resolve? |
//--------------------------------------------------------------- |
if (opcode_valid_i & resolve_failed) |
begin |
`ifdef CONF_CORE_DEBUG |
$display("%08x: Operand resolve failed RA=%d, RB=%d", opcode_pc_i, reg_ra_i, reg_rb_i); |
`endif |
// Stall! |
v_opcode_valid = 1'b0; |
v_stall = 1'b1; |
end |
|
//--------------------------------------------------------------- |
// Final instruction decoding |
//--------------------------------------------------------------- |
|
// Insert bubble into the pipeline? |
if (!v_opcode_valid) |
begin |
v_mem_data_in = `OPCODE_INST_BUBBLE; |
v_check_load_rd = 1'b0; |
end |
|
// Store opcode (after possible bubble generation) |
r_e_opcode <= v_mem_data_in; |
r_e_opcode_pc <= opcode_pc_i; |
|
// Decode instruction |
v_inst = {2'b00,v_mem_data_in[31:26]}; |
|
// Shift ammount (from register[rb]) |
v_shift_val = {26'b00,v_reg_rb[5:0]}; |
|
// Shift ammount (from immediate) |
v_shift_imm = {26'b00,v_imm[5:0]}; |
|
// MTSPR/MFSPR operand |
v_mxspr_imm = (v_reg_ra[15:0] | {5'b00000,v_mem_data_in[10:0]}); |
|
// Next expected PC (current PC + 4) |
v_pc = (opcode_pc_i + 4); |
|
// Latch carry if updated |
if (alu_carry_update) |
v_sr[`OR32_SR_CY] = alu_carry_out; |
|
`ifdef CONF_CORE_TRACE |
if (v_opcode_valid) |
begin |
$display("%08x: Execute 0x%08x", opcode_pc_i, v_mem_data_in); |
$display(" rA[%d] = 0x%08x", reg_ra_i, v_reg_ra); |
$display(" rB[%d] = 0x%08x", reg_rb_i, v_reg_rb); |
end |
`endif |
|
//--------------------------------------------------------------- |
// Execute instruction |
//--------------------------------------------------------------- |
case (v_inst) |
`INST_OR32_BUBBLE : |
begin |
// Do not allow external interrupts whilst executing a bubble |
// as this will result in pipeline issues. |
v_no_intr = 1'b1; |
end |
`INST_OR32_ALU : |
begin |
case (v_alu_op) |
`INST_OR32_ADD: // l.add |
begin |
r_e_alu_func <= `ALU_ADD; |
r_e_alu_a <= v_reg_ra; |
r_e_alu_b <= v_reg_rb; |
v_write_rd = 1'b1; |
end |
|
`INST_OR32_ADDC: // l.addc |
begin |
r_e_alu_func <= `ALU_ADDC; |
r_e_alu_a <= v_reg_ra; |
r_e_alu_b <= v_reg_rb; |
v_write_rd = 1'b1; |
end |
|
`INST_OR32_AND: // l.and |
begin |
r_e_alu_func <= `ALU_AND; |
r_e_alu_a <= v_reg_ra; |
r_e_alu_b <= v_reg_rb; |
v_write_rd = 1'b1; |
end |
|
`INST_OR32_OR: // l.or |
begin |
r_e_alu_func <= `ALU_OR; |
r_e_alu_a <= v_reg_ra; |
r_e_alu_b <= v_reg_rb; |
v_write_rd = 1'b1; |
end |
|
`INST_OR32_SLL: // l.sll |
begin |
r_e_alu_func <= `ALU_SHIFTL; |
r_e_alu_a <= v_reg_ra; |
r_e_alu_b <= v_shift_val; |
v_write_rd = 1'b1; |
end |
|
`INST_OR32_SRA: // l.sra |
begin |
r_e_alu_func <= `ALU_SHIRTR_ARITH; |
r_e_alu_a <= v_reg_ra; |
r_e_alu_b <= v_shift_val; |
v_write_rd = 1'b1; |
end |
|
`INST_OR32_SRL: // l.srl |
begin |
r_e_alu_func <= `ALU_SHIFTR; |
r_e_alu_a <= v_reg_ra; |
r_e_alu_b <= v_shift_val; |
v_write_rd = 1'b1; |
end |
|
`INST_OR32_SUB: // l.sub |
begin |
r_e_alu_func <= `ALU_SUB; |
r_e_alu_a <= v_reg_ra; |
r_e_alu_b <= v_reg_rb; |
v_write_rd = 1'b1; |
end |
|
`INST_OR32_XOR: // l.xor |
begin |
r_e_alu_func <= `ALU_XOR; |
r_e_alu_a <= v_reg_ra; |
r_e_alu_b <= v_reg_rb; |
v_write_rd = 1'b1; |
end |
|
default: |
begin |
fault_o <= 1'b1; |
v_exception = 1'b1; |
v_vector = ISR_VECTOR + `VECTOR_ILLEGAL_INST; |
end |
endcase |
end |
|
`INST_OR32_ADDI: // l.addi |
begin |
r_e_alu_func <= `ALU_ADD; |
r_e_alu_a <= v_reg_ra; |
r_e_alu_b <= v_imm_int32; |
v_write_rd = 1'b1; |
end |
|
`INST_OR32_ANDI: // l.andi |
begin |
r_e_alu_func <= `ALU_AND; |
r_e_alu_a <= v_reg_ra; |
r_e_alu_b <= v_imm_uint32; |
v_write_rd = 1'b1; |
end |
|
`INST_OR32_BF: // l.bf |
begin |
if (v_sr[`OR32_SR_F] == 1'b1) |
v_branch = 1'b1; |
end |
|
`INST_OR32_BNF: // l.bnf |
begin |
if (v_sr[`OR32_SR_F] == 1'b0) |
v_branch = 1'b1; |
end |
|
`INST_OR32_J: // l.j |
begin |
v_branch = 1'b1; |
end |
|
`INST_OR32_JAL: // l.jal |
begin |
r_e_alu_a <= v_pc; |
v_write_rd = 1'b1; |
v_rd = 5'b01001; // Write to REG_9_LR |
`ifdef CONF_CORE_DEBUG |
$display(" Save 0x%x to LR", v_pc); |
`endif |
v_branch = 1'b1; |
end |
|
`INST_OR32_JALR: // l.jalr |
begin |
r_e_alu_a <= v_pc; |
v_write_rd = 1'b1; |
v_rd = 5'b01001; // Write to REG_9_LR |
`ifdef CONF_CORE_DEBUG |
$display(" Save 0x%x to LR", v_pc); |
`endif |
v_pc = v_reg_rb; |
v_jmp = 1; |
end |
|
`INST_OR32_JR: // l.jr |
begin |
v_pc = v_reg_rb; |
v_jmp = 1; |
end |
|
// l.lbs l.lhs l.lws l.lbz l.lhz l.lwz |
`INST_OR32_LBS, `INST_OR32_LHS, `INST_OR32_LWS, `INST_OR32_LBZ, `INST_OR32_LHZ, `INST_OR32_LWZ : |
begin |
v_mem_addr = (v_reg_ra + v_imm_int32); |
dmem_addr_o <= v_mem_addr; |
dmem_data_out_o <= 32'h00000000; |
dmem_rd_o <= 1'b1; |
|
// Writeback if load result ready |
v_write_rd = 1'b1; |
v_check_load_rd = 1'b0; |
|
// Mark load as pending |
v_load_pending = 1'b1; |
r_mem_access <= 1'b1; |
|
// Record target register |
r_load_rd <= reg_rd_i; |
r_load_inst <= v_inst; |
r_load_offset<= v_mem_addr[1:0]; |
|
`ifdef CONF_CORE_DEBUG |
$display(" Load from 0x%08x to R%d", v_mem_addr, reg_rd_i); |
`endif |
// Detect bad load address & fault (ignore bit 31) |
if (v_mem_addr[30:28] != 3'h1) |
begin |
v_load_pending = 1'b0; |
dmem_rd_o <= 1'b0; |
r_mem_access <= 1'b0; |
fault_o <= 1'b1; |
v_exception = 1'b1; |
v_vector = ISR_VECTOR + `VECTOR_BUS_ERROR; |
end |
end |
|
`INST_OR32_MFSPR: // l.mfspr |
begin |
case (v_mxspr_imm) |
// SR - Supervision register |
`SPR_REG_SR: |
begin |
r_e_alu_a <= v_sr; |
v_write_rd = 1'b1; |
end |
|
// EPCR - EPC Exception saved PC |
`SPR_REG_EPCR: |
begin |
r_e_alu_a <= r_epc; |
v_write_rd = 1'b1; |
end |
|
// ESR - Exception saved SR |
`SPR_REG_ESR: |
begin |
r_e_alu_a <= r_esr; |
v_write_rd = 1'b1; |
end |
|
default: |
begin |
fault_o <= 1'b1; |
v_exception = 1'b1; |
v_vector = ISR_VECTOR + `VECTOR_ILLEGAL_INST; |
end |
endcase |
end |
|
`INST_OR32_MTSPR: // l.mtspr |
begin |
case (v_mxspr_imm) |
// SR - Supervision register |
`SPR_REG_SR: |
begin |
v_sr = v_reg_rb; |
|
// Cache flush request? |
icache_flush_o <= v_reg_rb[`OR32_SR_ICACHE_FLUSH]; |
dcache_flush_o <= v_reg_rb[`OR32_SR_DCACHE_FLUSH]; |
|
// Don't store cache flush requests |
v_sr[`OR32_SR_ICACHE_FLUSH] = 1'b0; |
v_sr[`OR32_SR_DCACHE_FLUSH] = 1'b0; |
end |
|
// EPCR - EPC Exception saved PC |
`SPR_REG_EPCR: |
begin |
r_epc <= v_reg_rb; |
end |
|
// ESR - Exception saved SR |
`SPR_REG_ESR: |
begin |
r_esr <= v_reg_rb; |
end |
|
default: |
begin |
fault_o <= 1'b1; |
v_exception = 1'b1; |
v_vector = ISR_VECTOR + `VECTOR_ILLEGAL_INST; |
end |
endcase |
end |
|
`INST_OR32_MOVHI: // l.movhi |
begin |
r_e_alu_a <= {v_imm,16'h0000}; |
v_write_rd = 1'b1; |
end |
|
`INST_OR32_NOP: // l.nop |
begin |
`ifdef SIMULATION |
case (v_imm) |
// NOP_PUTC |
16'h0004: $write("%c", v_reg_ra[7:0]); |
// NOP |
16'h0000: ; |
endcase |
`endif |
end |
|
`INST_OR32_ORI: // l.ori |
begin |
r_e_alu_func <= `ALU_OR; |
r_e_alu_a <= v_reg_ra; |
r_e_alu_b <= v_imm_uint32; |
v_write_rd = 1'b1; |
end |
|
`INST_OR32_RFE: // l.rfe |
begin |
v_pc = r_epc; |
v_sr = r_esr; |
v_jmp = 1; |
end |
|
`INST_OR32_SHIFTI : |
begin |
case (v_shift_op) |
`INST_OR32_SLLI: // l.slli |
begin |
r_e_alu_func <= `ALU_SHIFTL; |
r_e_alu_a <= v_reg_ra; |
r_e_alu_b <= v_shift_imm; |
v_write_rd = 1'b1; |
end |
|
`INST_OR32_SRAI: // l.srai |
begin |
r_e_alu_func <= `ALU_SHIRTR_ARITH; |
r_e_alu_a <= v_reg_ra; |
r_e_alu_b <= v_shift_imm; |
v_write_rd = 1'b1; |
end |
|
`INST_OR32_SRLI: // l.srli |
begin |
r_e_alu_func <= `ALU_SHIFTR; |
r_e_alu_a <= v_reg_ra; |
r_e_alu_b <= v_shift_imm; |
v_write_rd = 1'b1; |
end |
|
default: |
begin |
fault_o <= 1'b1; |
v_exception = 1'b1; |
v_vector = ISR_VECTOR + `VECTOR_ILLEGAL_INST; |
end |
endcase |
end |
|
`INST_OR32_SB: |
begin |
v_mem_addr = (v_reg_ra + v_store_imm); |
dmem_addr_o <= v_mem_addr; |
r_mem_access <= 1'b1; |
case (v_mem_addr[1:0]) |
2'b00 : |
begin |
dmem_data_out_o <= {v_reg_rb[7:0],24'h000000}; |
dmem_wr_o <= 4'b1000; |
v_store_pending = 1'b1; |
end |
2'b01 : |
begin |
dmem_data_out_o <= {{8'h00,v_reg_rb[7:0]},16'h0000}; |
dmem_wr_o <= 4'b0100; |
v_store_pending = 1'b1; |
end |
2'b10 : |
begin |
dmem_data_out_o <= {{16'h0000,v_reg_rb[7:0]},8'h00}; |
dmem_wr_o <= 4'b0010; |
v_store_pending = 1'b1; |
end |
2'b11 : |
begin |
dmem_data_out_o <= {24'h000000,v_reg_rb[7:0]}; |
dmem_wr_o <= 4'b0001; |
v_store_pending = 1'b1; |
end |
default : |
begin |
dmem_data_out_o <= 32'h00000000; |
dmem_wr_o <= 4'b0000; |
end |
endcase |
end |
|
`INST_OR32_SFXX, `INST_OR32_SFXXI: |
begin |
case (v_sfxx_op) |
`INST_OR32_SFEQ: // l.sfeq |
begin |
if (v_reg_ra == v_reg_rb) |
v_sr[`OR32_SR_F] = 1'b1; |
else |
v_sr[`OR32_SR_F] = 1'b0; |
end |
|
`INST_OR32_SFEQI: // l.sfeqi |
begin |
if (v_reg_ra == v_imm_int32) |
v_sr[`OR32_SR_F] = 1'b1; |
else |
v_sr[`OR32_SR_F] = 1'b0; |
end |
|
`INST_OR32_SFGES: // l.sfges |
begin |
if (greater_than_equal_signed(v_reg_ra, v_reg_rb) == 1'b1) |
v_sr[`OR32_SR_F] = 1'b1; |
else |
v_sr[`OR32_SR_F] = 1'b0; |
end |
|
`INST_OR32_SFGESI: // l.sfgesi |
begin |
if (greater_than_equal_signed(v_reg_ra, v_imm_int32) == 1'b1) |
v_sr[`OR32_SR_F] = 1'b1; |
else |
v_sr[`OR32_SR_F] = 1'b0; |
end |
|
`INST_OR32_SFGEU: // l.sfgeu |
begin |
if (v_reg_ra >= v_reg_rb) |
v_sr[`OR32_SR_F] = 1'b1; |
else |
v_sr[`OR32_SR_F] = 1'b0; |
end |
|
`INST_OR32_SFGEUI: // l.sfgeui |
begin |
if (v_reg_ra >= v_imm_int32) |
v_sr[`OR32_SR_F] = 1'b1; |
else |
v_sr[`OR32_SR_F] = 1'b0; |
end |
|
`INST_OR32_SFGTS: // l.sfgts |
begin |
if (greater_than_signed(v_reg_ra, v_reg_rb) == 1'b1) |
v_sr[`OR32_SR_F] = 1'b1; |
else |
v_sr[`OR32_SR_F] = 1'b0; |
end |
|
`INST_OR32_SFGTSI: // l.sfgtsi |
begin |
if (greater_than_signed(v_reg_ra, v_imm_int32) == 1'b1) |
v_sr[`OR32_SR_F] = 1'b1; |
else |
v_sr[`OR32_SR_F] = 1'b0; |
end |
|
`INST_OR32_SFGTU: // l.sfgtu |
begin |
if (v_reg_ra > v_reg_rb) |
v_sr[`OR32_SR_F] = 1'b1; |
else |
v_sr[`OR32_SR_F] = 1'b0; |
end |
|
`INST_OR32_SFGTUI: // l.sfgtui |
begin |
if (v_reg_ra > v_imm_int32) |
v_sr[`OR32_SR_F] = 1'b1; |
else |
v_sr[`OR32_SR_F] = 1'b0; |
end |
|
`INST_OR32_SFLES: // l.sfles |
begin |
if (less_than_equal_signed(v_reg_ra, v_reg_rb) == 1'b1) |
v_sr[`OR32_SR_F] = 1'b1; |
else |
v_sr[`OR32_SR_F] = 1'b0; |
end |
|
`INST_OR32_SFLESI: // l.sflesi |
begin |
if (less_than_equal_signed(v_reg_ra, v_imm_int32) == 1'b1) |
v_sr[`OR32_SR_F] = 1'b1; |
else |
v_sr[`OR32_SR_F] = 1'b0; |
end |
|
`INST_OR32_SFLEU: // l.sfleu |
begin |
if (v_reg_ra <= v_reg_rb) |
v_sr[`OR32_SR_F] = 1'b1; |
else |
v_sr[`OR32_SR_F] = 1'b0; |
end |
|
`INST_OR32_SFLEUI: // l.sfleui |
begin |
if (v_reg_ra <= v_imm_int32) |
v_sr[`OR32_SR_F] = 1'b1; |
else |
v_sr[`OR32_SR_F] = 1'b0; |
end |
|
`INST_OR32_SFLTS: // l.sflts |
begin |
if (less_than_signed(v_reg_ra, v_reg_rb) == 1'b1) |
v_sr[`OR32_SR_F] = 1'b1; |
else |
v_sr[`OR32_SR_F] = 1'b0; |
end |
|
`INST_OR32_SFLTSI: // l.sfltsi |
begin |
if (less_than_signed(v_reg_ra, v_imm_int32) == 1'b1) |
v_sr[`OR32_SR_F] = 1'b1; |
else |
v_sr[`OR32_SR_F] = 1'b0; |
end |
|
`INST_OR32_SFLTU: // l.sfltu |
begin |
if (v_reg_ra < v_reg_rb) |
v_sr[`OR32_SR_F] = 1'b1; |
else |
v_sr[`OR32_SR_F] = 1'b0; |
end |
|
`INST_OR32_SFLTUI: // l.sfltui |
begin |
if (v_reg_ra < v_imm_int32) |
v_sr[`OR32_SR_F] = 1'b1; |
else |
v_sr[`OR32_SR_F] = 1'b0; |
end |
|
`INST_OR32_SFNE: // l.sfne |
begin |
if (v_reg_ra != v_reg_rb) |
v_sr[`OR32_SR_F] = 1'b1; |
else |
v_sr[`OR32_SR_F] = 1'b0; |
end |
|
`INST_OR32_SFNEI: // l.sfnei |
begin |
if (v_reg_ra != v_imm_int32) |
v_sr[`OR32_SR_F] = 1'b1; |
else |
v_sr[`OR32_SR_F] = 1'b0; |
end |
|
default: |
begin |
fault_o <= 1'b1; |
v_exception = 1'b1; |
v_vector = ISR_VECTOR + `VECTOR_ILLEGAL_INST; |
end |
endcase |
end |
|
`INST_OR32_SH: // l.sh |
begin |
v_mem_addr = (v_reg_ra + v_store_imm); |
dmem_addr_o <= v_mem_addr; |
r_mem_access <= 1'b1; |
case (v_mem_addr[1:0]) |
2'b00 : |
begin |
dmem_data_out_o <= {v_reg_rb[15:0],16'h0000}; |
dmem_wr_o <= 4'b1100; |
v_store_pending = 1'b1; |
end |
2'b10 : |
begin |
dmem_data_out_o <= {16'h0000,v_reg_rb[15:0]}; |
dmem_wr_o <= 4'b0011; |
v_store_pending = 1'b1; |
end |
default : |
begin |
dmem_data_out_o <= 32'h00000000; |
dmem_wr_o <= 4'b0000; |
end |
endcase |
end |
|
`INST_OR32_SW: // l.sw |
begin |
v_mem_addr = (v_reg_ra + v_store_imm); |
dmem_addr_o <= v_mem_addr; |
dmem_data_out_o <= v_reg_rb; |
dmem_wr_o <= 4'b1111; |
r_mem_access <= 1'b1; |
v_store_pending = 1'b1; |
|
`ifdef CONF_CORE_DEBUG |
$display(" Store R%d to 0x%08x = 0x%08x", reg_rb_i, {v_mem_addr[31:2],2'b00}, v_reg_rb); |
`endif |
end |
|
`INST_OR32_MISC: |
begin |
case (v_mem_data_in[31:24]) |
`INST_OR32_SYS: // l.sys |
begin |
v_exception = 1'b1; |
v_vector = ISR_VECTOR + `VECTOR_SYSCALL; |
end |
|
`INST_OR32_TRAP: // l.trap |
begin |
v_exception = 1'b1; |
v_vector = ISR_VECTOR + `VECTOR_TRAP; |
break_o <= 1'b1; |
end |
|
default : |
begin |
fault_o <= 1'b1; |
v_exception = 1'b1; |
v_vector = ISR_VECTOR + `VECTOR_ILLEGAL_INST; |
end |
endcase |
end |
|
`INST_OR32_XORI: // l.xori |
begin |
r_e_alu_func <= `ALU_XOR; |
r_e_alu_a <= v_reg_ra; |
r_e_alu_b <= v_imm_int32; |
v_write_rd = 1'b1; |
end |
|
default : |
begin |
fault_o <= 1'b1; |
v_exception = 1'b1; |
v_vector = ISR_VECTOR + `VECTOR_ILLEGAL_INST; |
end |
endcase |
|
//--------------------------------------------------------------- |
// Branch logic |
//--------------------------------------------------------------- |
|
// If relative branch, calculate target before possible interrupt/exception |
if (v_branch == 1'b1) |
begin |
v_offset = {v_target[29:0],2'b00}; |
v_pc = (opcode_pc_i + v_offset); |
end |
|
// Pipeline stall due to load result not ready |
if (v_stall == 1'b1) |
begin |
// No exceptions whilst stalled |
end |
// Exception (Fault/Syscall/Break) |
else if (v_exception == 1'b1) |
begin |
// Save PC of next instruction |
r_epc <= v_pc; |
|
// Disable further interrupts |
r_esr <= v_sr; |
v_sr = 0; |
|
// Set PC to exception vector |
v_pc = v_vector; |
r_pc_branch <= v_pc; |
r_pc_fetch <= 1'b1; |
|
`ifdef CONF_CORE_DEBUG |
$display(" Exception 0x%08x", v_vector); |
`endif |
end |
// Non-maskable interrupt |
else if (nmi_i | r_nmi) |
begin |
r_nmi <= 1'b0; |
|
// Save PC of next instruction |
r_epc <= v_pc; |
|
// Disable further interrupts |
r_esr <= v_sr; |
v_sr = 0; |
|
// Set PC to exception vector |
v_pc = ISR_VECTOR + `VECTOR_NMI; |
r_pc_branch <= v_pc; |
r_pc_fetch <= 1'b1; |
|
`ifdef CONF_CORE_DEBUG |
$display(" NMI 0x%08x", v_pc); |
`endif |
end |
// External interrupt |
else if (v_no_intr == 1'b0 && |
((intr_i && v_sr[`OR32_SR_IEE]))) |
begin |
// Save PC of next instruction & SR |
r_epc <= v_pc; |
|
// Disable further interrupts |
r_esr <= v_sr; |
v_sr = 0; |
|
// Set PC to external interrupt vector |
v_pc = ISR_VECTOR + `VECTOR_EXTINT; |
|
r_pc_branch <= v_pc; |
r_pc_fetch <= 1'b1; |
|
`ifdef CONF_CORE_DEBUG |
$display(" External Interrupt 0x%08x", v_pc); |
`endif |
end |
// Handle relative branches (l.bf, l.bnf, l.j, l.jal) |
else if (v_branch == 1'b1) |
begin |
// Perform branch (already in v_pc) |
r_pc_branch <= v_pc; |
r_pc_fetch <= 1'b1; |
|
`ifdef CONF_CORE_DEBUG |
$display(" Branch to 0x%08x", v_pc); |
`endif |
end |
// Handle absolute jumps (l.jr, l.jalr, l.rfe) |
else if (v_jmp == 1'b1) |
begin |
// Perform branch |
r_pc_branch <= v_pc; |
r_pc_fetch <= 1'b1; |
|
`ifdef CONF_CORE_DEBUG |
$display(" Jump to 0x%08x", v_pc); |
`endif |
end |
|
|
// Update other registers with variable values |
r_stall <= v_stall; |
r_sr <= v_sr; |
|
// Memory access? |
r_mem_load <= v_load_pending; |
r_mem_store<= v_store_pending; |
|
// No writeback required? |
if (v_write_rd == 1'b0) |
begin |
// Target register is R0 which is read-only |
r_e_rd <= 5'b00000; |
end |
// Writeback required |
else |
begin |
// Load outstanding, check if result target is being |
// overwritten (to avoid WAR hazard) |
if (v_check_load_rd && v_rd == r_load_rd) |
begin |
`ifdef CONF_CORE_DEBUG |
if (v_rd != 5'b0) |
$display("%08x: Load target overwrite, clear target (R%d)", opcode_pc_i, r_load_rd); |
`endif |
|
// Ditch load result when it arrives |
r_load_rd <= 5'b00000; |
end |
|
// Target Rd |
r_e_rd <= v_rd; |
end |
end |
end |
|
//------------------------------------------------------------------- |
// Assignments |
//------------------------------------------------------------------- |
|
assign branch_pc_o = r_pc_branch; |
assign branch_o = r_pc_fetch; |
assign stall_o = r_stall; |
|
assign opcode_o = r_e_opcode; |
|
assign reg_rd_o = r_e_rd; |
assign reg_rd_value_o = r_e_result; |
|
assign mult_o = 1'b0; |
assign mult_res_o = 32'b0; |
|
`include "altor32_funcs.v" |
|
//------------------------------------------------------------------- |
// Hooks for debug |
//------------------------------------------------------------------- |
`ifdef verilator |
function [31:0] get_opcode_ex; |
// verilator public |
get_opcode_ex = r_e_opcode; |
endfunction |
function [31:0] get_pc_ex; |
// verilator public |
get_pc_ex = r_e_opcode_pc; |
endfunction |
`endif |
|
endmodule |
/rtl/cpu/altor32_regfile_sim.v
0,0 → 1,444
//----------------------------------------------------------------- |
// AltOR32 |
// Alternative Lightweight OpenRisc |
// V2.0 |
// Ultra-Embedded.com |
// Copyright 2011 - 2013 |
// |
// Email: admin@ultra-embedded.com |
// |
// License: LGPL |
//----------------------------------------------------------------- |
// |
// Copyright (C) 2011 - 2013 Ultra-Embedded.com |
// |
// This source file may be used and distributed without |
// restriction provided that this copyright statement is not |
// removed from the file and that any derivative work contains |
// the original copyright notice and the associated disclaimer. |
// |
// This source file is free software; you can redistribute it |
// and/or modify it under the terms of the GNU Lesser General |
// Public License as published by the Free Software Foundation; |
// either version 2.1 of the License, or (at your option) any |
// later version. |
// |
// This source is distributed in the hope that it will be |
// useful, but WITHOUT ANY WARRANTY; without even the implied |
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR |
// PURPOSE. See the GNU Lesser General Public License for more |
// details. |
// |
// You should have received a copy of the GNU Lesser General |
// Public License along with this source; if not, write to the |
// Free Software Foundation, Inc., 59 Temple Place, Suite 330, |
// Boston, MA 02111-1307 USA |
//----------------------------------------------------------------- |
|
//----------------------------------------------------------------- |
// Includes |
//----------------------------------------------------------------- |
`include "altor32_defs.v" |
|
//----------------------------------------------------------------- |
// Module - Simulation register file |
//----------------------------------------------------------------- |
module altor32_regfile_sim |
( |
input clk_i /*verilator public*/, |
input rst_i /*verilator public*/, |
input wr_i /*verilator public*/, |
input [4:0] rs_i /*verilator public*/, |
input [4:0] rt_i /*verilator public*/, |
input [4:0] rd_i /*verilator public*/, |
output [31:0] reg_rs_o /*verilator public*/, |
output [31:0] reg_rt_o /*verilator public*/, |
input [31:0] reg_rd_i /*verilator public*/ |
); |
|
//----------------------------------------------------------------- |
// Params |
//----------------------------------------------------------------- |
parameter SUPPORT_32REGS = "ENABLED"; |
|
//----------------------------------------------------------------- |
// Registers |
//----------------------------------------------------------------- |
|
// Register file |
reg [31:0] reg_r1_sp; |
reg [31:0] reg_r2_fp; |
reg [31:0] reg_r3; |
reg [31:0] reg_r4; |
reg [31:0] reg_r5; |
reg [31:0] reg_r6; |
reg [31:0] reg_r7; |
reg [31:0] reg_r8; |
reg [31:0] reg_r9_lr; |
reg [31:0] reg_r10; |
reg [31:0] reg_r11; |
reg [31:0] reg_r12; |
reg [31:0] reg_r13; |
reg [31:0] reg_r14; |
reg [31:0] reg_r15; |
reg [31:0] reg_r16; |
reg [31:0] reg_r17; |
reg [31:0] reg_r18; |
reg [31:0] reg_r19; |
reg [31:0] reg_r20; |
reg [31:0] reg_r21; |
reg [31:0] reg_r22; |
reg [31:0] reg_r23; |
reg [31:0] reg_r24; |
reg [31:0] reg_r25; |
reg [31:0] reg_r26; |
reg [31:0] reg_r27; |
reg [31:0] reg_r28; |
reg [31:0] reg_r29; |
reg [31:0] reg_r30; |
reg [31:0] reg_r31; |
|
reg [31:0] reg_rs_o; |
reg [31:0] reg_rt_o; |
|
//----------------------------------------------------------------- |
// Register File (for simulation) |
//----------------------------------------------------------------- |
|
// Synchronous register write back |
always @ (posedge clk_i or posedge rst_i) |
begin |
if (rst_i) |
begin |
reg_r1_sp <= 32'h00000000; |
reg_r2_fp <= 32'h00000000; |
reg_r3 <= 32'h00000000; |
reg_r4 <= 32'h00000000; |
reg_r5 <= 32'h00000000; |
reg_r6 <= 32'h00000000; |
reg_r7 <= 32'h00000000; |
reg_r8 <= 32'h00000000; |
reg_r9_lr <= 32'h00000000; |
reg_r10 <= 32'h00000000; |
reg_r11 <= 32'h00000000; |
reg_r12 <= 32'h00000000; |
reg_r13 <= 32'h00000000; |
reg_r14 <= 32'h00000000; |
reg_r15 <= 32'h00000000; |
reg_r16 <= 32'h00000000; |
reg_r17 <= 32'h00000000; |
reg_r18 <= 32'h00000000; |
reg_r19 <= 32'h00000000; |
reg_r20 <= 32'h00000000; |
reg_r21 <= 32'h00000000; |
reg_r22 <= 32'h00000000; |
reg_r23 <= 32'h00000000; |
reg_r24 <= 32'h00000000; |
reg_r25 <= 32'h00000000; |
reg_r26 <= 32'h00000000; |
reg_r27 <= 32'h00000000; |
reg_r28 <= 32'h00000000; |
reg_r29 <= 32'h00000000; |
reg_r30 <= 32'h00000000; |
reg_r31 <= 32'h00000000; |
end |
else |
begin |
if (wr_i == 1'b1) |
case (rd_i[4:0]) |
5'b00001 : |
reg_r1_sp <= reg_rd_i; |
5'b00010 : |
reg_r2_fp <= reg_rd_i; |
5'b00011 : |
reg_r3 <= reg_rd_i; |
5'b00100 : |
reg_r4 <= reg_rd_i; |
5'b00101 : |
reg_r5 <= reg_rd_i; |
5'b00110 : |
reg_r6 <= reg_rd_i; |
5'b00111 : |
reg_r7 <= reg_rd_i; |
5'b01000 : |
reg_r8 <= reg_rd_i; |
5'b01001 : |
reg_r9_lr <= reg_rd_i; |
5'b01010 : |
reg_r10 <= reg_rd_i; |
5'b01011 : |
reg_r11 <= reg_rd_i; |
5'b01100 : |
reg_r12 <= reg_rd_i; |
5'b01101 : |
reg_r13 <= reg_rd_i; |
5'b01110 : |
reg_r14 <= reg_rd_i; |
5'b01111 : |
reg_r15 <= reg_rd_i; |
5'b10000 : |
reg_r16 <= reg_rd_i; |
5'b10001 : |
reg_r17 <= reg_rd_i; |
5'b10010 : |
reg_r18 <= reg_rd_i; |
5'b10011 : |
reg_r19 <= reg_rd_i; |
5'b10100 : |
reg_r20 <= reg_rd_i; |
5'b10101 : |
reg_r21 <= reg_rd_i; |
5'b10110 : |
reg_r22 <= reg_rd_i; |
5'b10111 : |
reg_r23 <= reg_rd_i; |
5'b11000 : |
reg_r24 <= reg_rd_i; |
5'b11001 : |
reg_r25 <= reg_rd_i; |
5'b11010 : |
reg_r26 <= reg_rd_i; |
5'b11011 : |
reg_r27 <= reg_rd_i; |
5'b11100 : |
reg_r28 <= reg_rd_i; |
5'b11101 : |
reg_r29 <= reg_rd_i; |
5'b11110 : |
reg_r30 <= reg_rd_i; |
5'b11111 : |
reg_r31 <= reg_rd_i; |
default : |
; |
endcase |
end |
end |
|
generate |
if (SUPPORT_32REGS == "ENABLED") |
begin |
// Asynchronous Register read (Rs & Rd) |
always @ * |
begin |
case (rs_i) |
5'b00000 : |
reg_rs_o = 32'h00000000; |
5'b00001 : |
reg_rs_o = reg_r1_sp; |
5'b00010 : |
reg_rs_o = reg_r2_fp; |
5'b00011 : |
reg_rs_o = reg_r3; |
5'b00100 : |
reg_rs_o = reg_r4; |
5'b00101 : |
reg_rs_o = reg_r5; |
5'b00110 : |
reg_rs_o = reg_r6; |
5'b00111 : |
reg_rs_o = reg_r7; |
5'b01000 : |
reg_rs_o = reg_r8; |
5'b01001 : |
reg_rs_o = reg_r9_lr; |
5'b01010 : |
reg_rs_o = reg_r10; |
5'b01011 : |
reg_rs_o = reg_r11; |
5'b01100 : |
reg_rs_o = reg_r12; |
5'b01101 : |
reg_rs_o = reg_r13; |
5'b01110 : |
reg_rs_o = reg_r14; |
5'b01111 : |
reg_rs_o = reg_r15; |
5'b10000 : |
reg_rs_o = reg_r16; |
5'b10001 : |
reg_rs_o = reg_r17; |
5'b10010 : |
reg_rs_o = reg_r18; |
5'b10011 : |
reg_rs_o = reg_r19; |
5'b10100 : |
reg_rs_o = reg_r20; |
5'b10101 : |
reg_rs_o = reg_r21; |
5'b10110 : |
reg_rs_o = reg_r22; |
5'b10111 : |
reg_rs_o = reg_r23; |
5'b11000 : |
reg_rs_o = reg_r24; |
5'b11001 : |
reg_rs_o = reg_r25; |
5'b11010 : |
reg_rs_o = reg_r26; |
5'b11011 : |
reg_rs_o = reg_r27; |
5'b11100 : |
reg_rs_o = reg_r28; |
5'b11101 : |
reg_rs_o = reg_r29; |
5'b11110 : |
reg_rs_o = reg_r30; |
5'b11111 : |
reg_rs_o = reg_r31; |
default : |
reg_rs_o = 32'h00000000; |
endcase |
|
case (rt_i) |
5'b00000 : |
reg_rt_o = 32'h00000000; |
5'b00001 : |
reg_rt_o = reg_r1_sp; |
5'b00010 : |
reg_rt_o = reg_r2_fp; |
5'b00011 : |
reg_rt_o = reg_r3; |
5'b00100 : |
reg_rt_o = reg_r4; |
5'b00101 : |
reg_rt_o = reg_r5; |
5'b00110 : |
reg_rt_o = reg_r6; |
5'b00111 : |
reg_rt_o = reg_r7; |
5'b01000 : |
reg_rt_o = reg_r8; |
5'b01001 : |
reg_rt_o = reg_r9_lr; |
5'b01010 : |
reg_rt_o = reg_r10; |
5'b01011 : |
reg_rt_o = reg_r11; |
5'b01100 : |
reg_rt_o = reg_r12; |
5'b01101 : |
reg_rt_o = reg_r13; |
5'b01110 : |
reg_rt_o = reg_r14; |
5'b01111 : |
reg_rt_o = reg_r15; |
5'b10000 : |
reg_rt_o = reg_r16; |
5'b10001 : |
reg_rt_o = reg_r17; |
5'b10010 : |
reg_rt_o = reg_r18; |
5'b10011 : |
reg_rt_o = reg_r19; |
5'b10100 : |
reg_rt_o = reg_r20; |
5'b10101 : |
reg_rt_o = reg_r21; |
5'b10110 : |
reg_rt_o = reg_r22; |
5'b10111 : |
reg_rt_o = reg_r23; |
5'b11000 : |
reg_rt_o = reg_r24; |
5'b11001 : |
reg_rt_o = reg_r25; |
5'b11010 : |
reg_rt_o = reg_r26; |
5'b11011 : |
reg_rt_o = reg_r27; |
5'b11100 : |
reg_rt_o = reg_r28; |
5'b11101 : |
reg_rt_o = reg_r29; |
5'b11110 : |
reg_rt_o = reg_r30; |
5'b11111 : |
reg_rt_o = reg_r31; |
default : |
reg_rt_o = 32'h00000000; |
endcase |
end |
end |
else |
begin |
// Asynchronous Register read (Rs & Rd) |
always @ * |
begin |
case (rs_i) |
5'b00000 : |
reg_rs_o = 32'h00000000; |
5'b00001 : |
reg_rs_o = reg_r1_sp; |
5'b00010 : |
reg_rs_o = reg_r2_fp; |
5'b00011 : |
reg_rs_o = reg_r3; |
5'b00100 : |
reg_rs_o = reg_r4; |
5'b00101 : |
reg_rs_o = reg_r5; |
5'b00110 : |
reg_rs_o = reg_r6; |
5'b00111 : |
reg_rs_o = reg_r7; |
5'b01000 : |
reg_rs_o = reg_r8; |
5'b01001 : |
reg_rs_o = reg_r9_lr; |
5'b01010 : |
reg_rs_o = reg_r10; |
5'b01011 : |
reg_rs_o = reg_r11; |
5'b01100 : |
reg_rs_o = reg_r12; |
5'b01101 : |
reg_rs_o = reg_r13; |
5'b01110 : |
reg_rs_o = reg_r14; |
5'b01111 : |
reg_rs_o = reg_r15; |
default : |
reg_rs_o = 32'h00000000; |
endcase |
|
case (rt_i) |
5'b00000 : |
reg_rt_o = 32'h00000000; |
5'b00001 : |
reg_rt_o = reg_r1_sp; |
5'b00010 : |
reg_rt_o = reg_r2_fp; |
5'b00011 : |
reg_rt_o = reg_r3; |
5'b00100 : |
reg_rt_o = reg_r4; |
5'b00101 : |
reg_rt_o = reg_r5; |
5'b00110 : |
reg_rt_o = reg_r6; |
5'b00111 : |
reg_rt_o = reg_r7; |
5'b01000 : |
reg_rt_o = reg_r8; |
5'b01001 : |
reg_rt_o = reg_r9_lr; |
5'b01010 : |
reg_rt_o = reg_r10; |
5'b01011 : |
reg_rt_o = reg_r11; |
5'b01100 : |
reg_rt_o = reg_r12; |
5'b01101 : |
reg_rt_o = reg_r13; |
5'b01110 : |
reg_rt_o = reg_r14; |
5'b01111 : |
reg_rt_o = reg_r15; |
default : |
reg_rt_o = 32'h00000000; |
endcase |
end |
end |
endgenerate |
|
endmodule |
/rtl/cpu/altor32_lfu.v
0,0 → 1,137
//----------------------------------------------------------------- |
// AltOR32 |
// Alternative Lightweight OpenRisc |
// V2.0 |
// Ultra-Embedded.com |
// Copyright 2011 - 2013 |
// |
// Email: admin@ultra-embedded.com |
// |
// License: LGPL |
//----------------------------------------------------------------- |
// |
// Copyright (C) 2011 - 2013 Ultra-Embedded.com |
// |
// This source file may be used and distributed without |
// restriction provided that this copyright statement is not |
// removed from the file and that any derivative work contains |
// the original copyright notice and the associated disclaimer. |
// |
// This source file is free software; you can redistribute it |
// and/or modify it under the terms of the GNU Lesser General |
// Public License as published by the Free Software Foundation; |
// either version 2.1 of the License, or (at your option) any |
// later version. |
// |
// This source is distributed in the hope that it will be |
// useful, but WITHOUT ANY WARRANTY; without even the implied |
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR |
// PURPOSE. See the GNU Lesser General Public License for more |
// details. |
// |
// You should have received a copy of the GNU Lesser General |
// Public License along with this source; if not, write to the |
// Free Software Foundation, Inc., 59 Temple Place, Suite 330, |
// Boston, MA 02111-1307 USA |
//----------------------------------------------------------------- |
|
//----------------------------------------------------------------- |
// Includes |
//----------------------------------------------------------------- |
`include "altor32_defs.v" |
|
//----------------------------------------------------------------- |
// Module: Load Forwarding Unit |
//----------------------------------------------------------------- |
module altor32_lfu |
( |
// Opcode |
input [7:0] opcode_i /*verilator public*/, |
|
// Memory load result |
input [31:0] mem_result_i /*verilator public*/, |
input [1:0] mem_offset_i /*verilator public*/, |
|
// Result |
output reg [31:0] load_result_o /*verilator public*/, |
output reg load_insn_o /*verilator public*/ |
); |
|
//------------------------------------------------------------------- |
// Load forwarding unit |
//------------------------------------------------------------------- |
always @ * |
begin |
load_result_o = 32'h00000000; |
load_insn_o = 1'b0; |
|
case (opcode_i) |
|
`INST_OR32_LBS: // l.lbs |
begin |
case (mem_offset_i) |
2'b00 : load_result_o[7:0] = mem_result_i[31:24]; |
2'b01 : load_result_o[7:0] = mem_result_i[23:16]; |
2'b10 : load_result_o[7:0] = mem_result_i[15:8]; |
2'b11 : load_result_o[7:0] = mem_result_i[7:0]; |
default : ; |
endcase |
|
// Sign extend LB |
if (load_result_o[7] == 1'b1) |
load_result_o[31:8] = 24'hFFFFFF; |
|
load_insn_o = 1'b1; |
end |
|
`INST_OR32_LBZ: // l.lbz |
begin |
case (mem_offset_i) |
2'b00 : load_result_o[7:0] = mem_result_i[31:24]; |
2'b01 : load_result_o[7:0] = mem_result_i[23:16]; |
2'b10 : load_result_o[7:0] = mem_result_i[15:8]; |
2'b11 : load_result_o[7:0] = mem_result_i[7:0]; |
default : ; |
endcase |
|
load_insn_o = 1'b1; |
end |
|
`INST_OR32_LHS: // l.lhs |
begin |
case (mem_offset_i) |
2'b00 : load_result_o[15:0] = mem_result_i[31:16]; |
2'b10 : load_result_o[15:0] = mem_result_i[15:0]; |
default : ; |
endcase |
|
// Sign extend LH |
if (load_result_o[15] == 1'b1) |
load_result_o[31:16] = 16'hFFFF; |
|
load_insn_o = 1'b1; |
end |
|
`INST_OR32_LHZ: // l.lhz |
begin |
case (mem_offset_i) |
2'b00 : load_result_o[15:0] = mem_result_i[31:16]; |
2'b10 : load_result_o[15:0] = mem_result_i[15:0]; |
default : ; |
endcase |
|
load_insn_o = 1'b1; |
end |
|
`INST_OR32_LWZ, `INST_OR32_LWS: // l.lwz l.lws |
begin |
load_result_o = mem_result_i; |
load_insn_o = 1'b1; |
end |
|
default : |
; |
endcase |
end |
|
endmodule |
/rtl/cpu/altor32_fetch.v
0,0 → 1,186
//----------------------------------------------------------------- |
// AltOR32 |
// Alternative Lightweight OpenRisc |
// V2.0 |
// Ultra-Embedded.com |
// Copyright 2011 - 2013 |
// |
// Email: admin@ultra-embedded.com |
// |
// License: LGPL |
//----------------------------------------------------------------- |
// |
// Copyright (C) 2011 - 2013 Ultra-Embedded.com |
// |
// This source file may be used and distributed without |
// restriction provided that this copyright statement is not |
// removed from the file and that any derivative work contains |
// the original copyright notice and the associated disclaimer. |
// |
// This source file is free software; you can redistribute it |
// and/or modify it under the terms of the GNU Lesser General |
// Public License as published by the Free Software Foundation; |
// either version 2.1 of the License, or (at your option) any |
// later version. |
// |
// This source is distributed in the hope that it will be |
// useful, but WITHOUT ANY WARRANTY; without even the implied |
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR |
// PURPOSE. See the GNU Lesser General Public License for more |
// details. |
// |
// You should have received a copy of the GNU Lesser General |
// Public License along with this source; if not, write to the |
// Free Software Foundation, Inc., 59 Temple Place, Suite 330, |
// Boston, MA 02111-1307 USA |
//----------------------------------------------------------------- |
|
//`define CONF_FETCH_DEBUG |
|
//----------------------------------------------------------------- |
// Includes |
//----------------------------------------------------------------- |
`include "altor32_defs.v" |
|
//----------------------------------------------------------------- |
// Module - Instruction Fetch |
//----------------------------------------------------------------- |
module altor32_fetch |
( |
// General |
input clk_i /*verilator public*/, |
input rst_i /*verilator public*/, |
|
// Instruction Fetch |
output fetch_o /*verilator public*/, |
output [31:0] pc_o /*verilator public*/, |
input [31:0] data_i /*verilator public*/, |
input data_valid_i/*verilator public*/, |
|
// Branch target |
input branch_i /*verilator public*/, |
input [31:0] branch_pc_i /*verilator public*/, |
input stall_i /*verilator public*/, |
|
// Decoded opcode |
output [31:0] opcode_o /*verilator public*/, |
output [31:0] opcode_pc_o /*verilator public*/, |
output opcode_valid_o /*verilator public*/, |
|
// Decoded register details |
output [4:0] ra_o /*verilator public*/, |
output [4:0] rb_o /*verilator public*/, |
output [4:0] rd_o /*verilator public*/ |
); |
|
//----------------------------------------------------------------- |
// Params |
//----------------------------------------------------------------- |
parameter BOOT_VECTOR = 32'h00000000; |
parameter CACHE_LINE_SIZE_WIDTH = 5; /* 5-bits -> 32 entries */ |
|
//----------------------------------------------------------------- |
// Registers |
//----------------------------------------------------------------- |
reg [31:0] r_pc; |
reg r_rd; |
reg [31:0] r_last_opcode; |
reg [31:0] r_last_pc; |
reg r_last_valid; |
reg [31:0] d_pc; |
|
//------------------------------------------------------------------- |
// Next PC state machine |
//------------------------------------------------------------------- |
reg [31:0] v_pc; |
|
always @ (posedge clk_i or posedge rst_i) |
begin |
if (rst_i) |
begin |
r_pc <= BOOT_VECTOR + `VECTOR_RESET; |
d_pc <= BOOT_VECTOR + `VECTOR_RESET; |
r_rd <= 1'b1; |
end |
else |
begin |
r_rd <= 1'b0; |
d_pc <= pc_o; |
|
// Branch - Next PC = branch target + 4 |
if (branch_i) |
begin |
r_pc <= branch_pc_i + 4; |
end |
// Stall - rollback to previous PC + 4 |
else if (stall_i) |
begin |
r_pc <= d_pc + 4; |
end |
// Normal sequential execution (and instruction is ready) |
else if (data_valid_i) |
begin |
v_pc = r_pc + 4; |
|
// New cache line? |
if (v_pc[CACHE_LINE_SIZE_WIDTH-1:0] == {CACHE_LINE_SIZE_WIDTH{1'b0}}) |
begin |
// Start fetch of next line |
r_rd <= 1'b1; |
end |
|
r_pc <= v_pc; |
end |
end |
end |
|
//------------------------------------------------------------------- |
// Pipeline storage of last PC/opcode passed to exec stage |
//------------------------------------------------------------------- |
always @ (posedge clk_i or posedge rst_i) |
begin |
if (rst_i) |
begin |
r_last_opcode <= 32'b0; |
r_last_pc <= 32'b0; |
r_last_valid <= 1'b0; |
|
end |
else |
begin |
// Record last valid instruction passed to exec stage |
if (!stall_i | !data_valid_i) |
begin |
r_last_pc <= opcode_pc_o; |
r_last_opcode <= opcode_o; |
r_last_valid <= opcode_valid_o; |
end |
end |
end |
|
//------------------------------------------------------------------- |
// Assignments |
//------------------------------------------------------------------- |
|
// Instruction Fetch |
assign pc_o = stall_i ? d_pc : (branch_i ? branch_pc_i : (~data_valid_i ? d_pc : r_pc)); |
assign fetch_o = branch_i ? 1'b1 : r_rd; |
|
// Opcode output |
assign opcode_valid_o = stall_i ? r_last_valid : (data_valid_i & !branch_i); |
assign opcode_o = stall_i ? r_last_opcode : (opcode_valid_o ? data_i : 32'b0); |
assign opcode_pc_o = stall_i ? r_last_pc : (opcode_valid_o ? d_pc : 32'b0); |
|
// If simulation, RA = 03 if NOP instruction |
`ifdef SIMULATION |
wire [7:0] v_fetch_inst = {2'b00, opcode_o[31:26]}; |
wire v_is_nop = (v_fetch_inst == `INST_OR32_NOP); |
assign ra_o = v_is_nop ? 5'd3 : opcode_o[20:16]; |
`else |
assign ra_o = opcode_o[20:16]; |
`endif |
|
assign rb_o = opcode_o[15:11]; |
assign rd_o = opcode_o[25:21]; |
|
endmodule |
/rtl/cpu/altor32_regfile_xil.v
0,0 → 1,145
//----------------------------------------------------------------- |
// AltOR32 |
// Alternative Lightweight OpenRisc |
// V2.0 |
// Ultra-Embedded.com |
// Copyright 2011 - 2013 |
// |
// Email: admin@ultra-embedded.com |
// |
// License: LGPL |
//----------------------------------------------------------------- |
// |
// Copyright (C) 2011 - 2013 Ultra-Embedded.com |
// |
// This source file may be used and distributed without |
// restriction provided that this copyright statement is not |
// removed from the file and that any derivative work contains |
// the original copyright notice and the associated disclaimer. |
// |
// This source file is free software; you can redistribute it |
// and/or modify it under the terms of the GNU Lesser General |
// Public License as published by the Free Software Foundation; |
// either version 2.1 of the License, or (at your option) any |
// later version. |
// |
// This source is distributed in the hope that it will be |
// useful, but WITHOUT ANY WARRANTY; without even the implied |
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR |
// PURPOSE. See the GNU Lesser General Public License for more |
// details. |
// |
// You should have received a copy of the GNU Lesser General |
// Public License along with this source; if not, write to the |
// Free Software Foundation, Inc., 59 Temple Place, Suite 330, |
// Boston, MA 02111-1307 USA |
//----------------------------------------------------------------- |
|
//----------------------------------------------------------------- |
// Includes |
//----------------------------------------------------------------- |
`include "altor32_defs.v" |
|
//----------------------------------------------------------------- |
// Module - Xilinx register file (async read) |
//----------------------------------------------------------------- |
module altor32_regfile_xil |
( |
input clk_i /*verilator public*/, |
input rst_i /*verilator public*/, |
input wr_i /*verilator public*/, |
input [4:0] rs_i /*verilator public*/, |
input [4:0] rt_i /*verilator public*/, |
input [4:0] rd_i /*verilator public*/, |
output reg [31:0] reg_rs_o /*verilator public*/, |
output reg [31:0] reg_rt_o /*verilator public*/, |
input [31:0] reg_rd_i /*verilator public*/ |
); |
|
//----------------------------------------------------------------- |
// Params |
//----------------------------------------------------------------- |
parameter SUPPORT_32REGS = "ENABLED"; |
|
//----------------------------------------------------------------- |
// Registers |
//----------------------------------------------------------------- |
reg [4:0] addr_write; |
wire [31:0] data_out1; |
wire [31:0] data_out2; |
reg write_enable; |
wire [31:0] data_out1a; |
wire [31:0] data_out1b; |
wire [31:0] data_out2a; |
wire [31:0] data_out2b; |
wire wea; |
wire web; |
|
//----------------------------------------------------------------- |
// Async Read Process |
//----------------------------------------------------------------- |
always @ (clk_i or rs_i or rt_i or rd_i or reg_rd_i or data_out1 or data_out2 or rst_i or wr_i) |
begin |
// Read Rs |
if (rs_i == 5'b00000) |
reg_rs_o <= 32'h00000000; |
else |
reg_rs_o <= data_out1; |
|
// Read Rt |
if (rt_i == 5'b00000) |
reg_rt_o <= 32'h00000000; |
else |
reg_rt_o <= data_out2; |
|
// Write enabled? |
addr_write <= rd_i[4:0]; |
if ((rd_i != 5'b00000) & (wr_i == 1'b1)) |
write_enable <= 1'b1; |
else |
write_enable <= 1'b0; |
end |
|
//----------------------------------------------------------------- |
// Register File (using RAM16X1D ) |
//----------------------------------------------------------------- |
|
// Registers 0 - 15 |
generate |
begin |
genvar i; |
for (i=0;i<32;i=i+1) |
begin : reg_loop1 |
RAM16X1D reg_bit1a(.WCLK(clk_i), .WE(wea), .A0(addr_write[0]), .A1(addr_write[1]), .A2(addr_write[2]), .A3(addr_write[3]), .D(reg_rd_i[i]), .DPRA0(rs_i[0]), .DPRA1(rs_i[1]), .DPRA2(rs_i[2]), .DPRA3(rs_i[3]), .DPO(data_out1a[i]), .SPO(/* open */)); |
RAM16X1D reg_bit1b(.WCLK(clk_i), .WE(web), .A0(addr_write[0]), .A1(addr_write[1]), .A2(addr_write[2]), .A3(addr_write[3]), .D(reg_rd_i[i]), .DPRA0(rs_i[0]), .DPRA1(rs_i[1]), .DPRA2(rs_i[2]), .DPRA3(rs_i[3]), .DPO(data_out1b[i]), .SPO(/* open */)); |
end |
end |
endgenerate |
|
// Registers 16 - 31 |
generate |
if (SUPPORT_32REGS == "ENABLED") |
begin |
genvar i; |
for (i=0;i<32;i=i+1) |
begin : reg_loop2 |
RAM16X1D reg_bit2a(.WCLK(clk_i), .WE(wea), .A0(addr_write[0]), .A1(addr_write[1]), .A2(addr_write[2]), .A3(addr_write[3]), .D(reg_rd_i[i]), .DPRA0(rt_i[0]), .DPRA1(rt_i[1]), .DPRA2(rt_i[2]), .DPRA3(rt_i[3]), .DPO(data_out2a[i]), .SPO(/* open */)); |
RAM16X1D reg_bit2b(.WCLK(clk_i), .WE(web), .A0(addr_write[0]), .A1(addr_write[1]), .A2(addr_write[2]), .A3(addr_write[3]), .D(reg_rd_i[i]), .DPRA0(rt_i[0]), .DPRA1(rt_i[1]), .DPRA2(rt_i[2]), .DPRA3(rt_i[3]), .DPO(data_out2b[i]), .SPO(/* open */)); |
end |
end |
else |
begin |
assign data_out2a = 32'h00000000; |
assign data_out2b = 32'h00000000; |
end |
endgenerate |
|
//----------------------------------------------------------------- |
// Combinatorial Assignments |
//----------------------------------------------------------------- |
assign data_out1 = (rs_i[4] == 1'b0) ? data_out1a : data_out1b; |
assign data_out2 = (rt_i[4] == 1'b0) ? data_out2a : data_out2b; |
assign wea = (write_enable & ~ (addr_write[4])); |
assign web = (write_enable & addr_write[4]); |
|
endmodule |
/rtl/cpu/altor32_ram_dp.v
0,0 → 1,94
//----------------------------------------------------------------- |
// AltOR32 |
// Alternative Lightweight OpenRisc |
// V2.0 |
// Ultra-Embedded.com |
// Copyright 2011 - 2013 |
// |
// Email: admin@ultra-embedded.com |
// |
// License: LGPL |
//----------------------------------------------------------------- |
// |
// Copyright (C) 2011 - 2013 Ultra-Embedded.com |
// |
// This source file may be used and distributed without |
// restriction provided that this copyright statement is not |
// removed from the file and that any derivative work contains |
// the original copyright notice and the associated disclaimer. |
// |
// This source file is free software; you can redistribute it |
// and/or modify it under the terms of the GNU Lesser General |
// Public License as published by the Free Software Foundation; |
// either version 2.1 of the License, or (at your option) any |
// later version. |
// |
// This source is distributed in the hope that it will be |
// useful, but WITHOUT ANY WARRANTY; without even the implied |
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR |
// PURPOSE. See the GNU Lesser General Public License for more |
// details. |
// |
// You should have received a copy of the GNU Lesser General |
// Public License along with this source; if not, write to the |
// Free Software Foundation, Inc., 59 Temple Place, Suite 330, |
// Boston, MA 02111-1307 USA |
//----------------------------------------------------------------- |
|
//----------------------------------------------------------------- |
// Module: altor32_ram_dp - Dual port RAM (used in cache) |
//----------------------------------------------------------------- |
module altor32_ram_dp |
( |
input aclk_i /*verilator public*/, |
output [(WIDTH - 1):0] adat_o /*verilator public*/, |
input [(WIDTH - 1):0] adat_i /*verilator public*/, |
input [(SIZE - 1):0] aadr_i /*verilator public*/, |
input awr_i /*verilator public*/, |
|
input bclk_i /*verilator public*/, |
output [(WIDTH - 1):0] bdat_o /*verilator public*/, |
input [(WIDTH - 1):0] bdat_i /*verilator public*/, |
input [(SIZE - 1):0] badr_i /*verilator public*/, |
input bwr_i /*verilator public*/ |
); |
|
//----------------------------------------------------------------- |
// Params |
//----------------------------------------------------------------- |
parameter [31:0] WIDTH = 8; |
parameter [31:0] SIZE = 14; |
|
//----------------------------------------------------------------- |
// Registers |
//----------------------------------------------------------------- |
/* verilator lint_off MULTIDRIVEN */ |
reg [(WIDTH - 1):0] ram [((2<< (SIZE-1)) - 1):0] /*verilator public*/; |
/* verilator lint_on MULTIDRIVEN */ |
|
reg [(SIZE - 1):0] rd_addr_a; |
reg [(SIZE - 1):0] rd_addr_b; |
|
//----------------------------------------------------------------- |
// Processes |
//----------------------------------------------------------------- |
always @ (posedge aclk_i) |
begin |
if (awr_i == 1'b1) |
ram[aadr_i] <= adat_i; |
rd_addr_a <= aadr_i; |
end |
always @ (posedge bclk_i) |
begin |
if (bwr_i == 1'b1) |
ram[badr_i] <= bdat_i; |
rd_addr_b <= badr_i; |
end |
|
//------------------------------------------------------------------- |
// Combinatorial |
//------------------------------------------------------------------- |
assign adat_o = ram[rd_addr_a]; |
assign bdat_o = ram[rd_addr_b]; |
|
endmodule |
/rtl/cpu/altor32_lsu.v
0,0 → 1,159
//----------------------------------------------------------------- |
// AltOR32 |
// Alternative Lightweight OpenRisc |
// V2.0 |
// Ultra-Embedded.com |
// Copyright 2011 - 2013 |
// |
// Email: admin@ultra-embedded.com |
// |
// License: LGPL |
//----------------------------------------------------------------- |
// |
// Copyright (C) 2011 - 2013 Ultra-Embedded.com |
// |
// This source file may be used and distributed without |
// restriction provided that this copyright statement is not |
// removed from the file and that any derivative work contains |
// the original copyright notice and the associated disclaimer. |
// |
// This source file is free software; you can redistribute it |
// and/or modify it under the terms of the GNU Lesser General |
// Public License as published by the Free Software Foundation; |
// either version 2.1 of the License, or (at your option) any |
// later version. |
// |
// This source is distributed in the hope that it will be |
// useful, but WITHOUT ANY WARRANTY; without even the implied |
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR |
// PURPOSE. See the GNU Lesser General Public License for more |
// details. |
// |
// You should have received a copy of the GNU Lesser General |
// Public License along with this source; if not, write to the |
// Free Software Foundation, Inc., 59 Temple Place, Suite 330, |
// Boston, MA 02111-1307 USA |
//----------------------------------------------------------------- |
|
//----------------------------------------------------------------- |
// Includes |
//----------------------------------------------------------------- |
`include "altor32_defs.v" |
|
//----------------------------------------------------------------- |
// Module: Load / Store Unit |
//----------------------------------------------------------------- |
module altor32_lsu |
( |
// Current instruction |
input opcode_valid_i /*verilator public*/, |
input [7:0] opcode_i /*verilator public*/, |
|
// Load / Store pending |
input load_pending_i /*verilator public*/, |
input store_pending_i /*verilator public*/, |
|
// Load dest register |
input [4:0] rd_load_i /*verilator public*/, |
|
// Load insn in WB stage |
input load_wb_i /*verilator public*/, |
|
// Memory status |
input mem_access_i /*verilator public*/, |
input mem_ack_i /*verilator public*/, |
|
// Load / store still pending |
output reg load_pending_o /*verilator public*/, |
output reg store_pending_o /*verilator public*/, |
|
// Insert load result into pipeline |
output reg write_result_o /*verilator public*/, |
|
// Stall pipeline due load / store / insert |
output reg stall_o /*verilator public*/ |
); |
|
//------------------------------------------------------------------- |
// Outstanding memory access logic |
//------------------------------------------------------------------- |
reg v_inst_load; |
reg v_inst_store; |
|
always @ * |
begin |
|
load_pending_o = load_pending_i; |
store_pending_o = store_pending_i; |
stall_o = 1'b0; |
write_result_o = 1'b0; |
|
// Is this instruction a load or store? |
v_inst_load = is_load_operation(opcode_i); |
v_inst_store = is_store_operation(opcode_i); |
|
// Store operation just completed? |
if (store_pending_o & mem_ack_i & ~mem_access_i) |
begin |
`ifdef CONF_CORE_DEBUG |
$display(" Store operation now completed"); |
`endif |
store_pending_o = 1'b0; |
end |
|
// Load just completed (and result ready in-time for writeback stage)? |
if (load_pending_o & mem_ack_i & ~mem_access_i & load_wb_i) |
begin |
// Load complete |
load_pending_o = 1'b0; |
|
`ifdef CONF_CORE_DEBUG |
$display(" Load operation completed in writeback stage"); |
`endif |
end |
// Load just completed (later than writeback stage)? |
else if (load_pending_o & mem_ack_i & ~mem_access_i) |
begin |
`ifdef CONF_CORE_DEBUG |
$display(" Load operation completed later than writeback stage"); |
`endif |
|
// Valid target register? |
if (rd_load_i != 5'b00000) |
begin |
`ifdef CONF_CORE_DEBUG |
$display(" Load result now ready for R%d", rd_load_i); |
`endif |
// Stall instruction and write load result to pipeline |
stall_o = opcode_valid_i; |
write_result_o = 1'b1; |
end |
else |
begin |
`ifdef CONF_CORE_DEBUG |
$display(" Load result ready but not needed"); |
`endif |
end |
|
// Load complete |
load_pending_o = 1'b0; |
end |
|
// If load or store in progress (and this instruction is valid) |
if ((load_pending_o | store_pending_o) & opcode_valid_i) |
begin |
// Load or store whilst memory bus busy |
if (v_inst_load | v_inst_store) |
begin |
`ifdef CONF_CORE_DEBUG |
$display(" Data bus already busy, stall (load_pending_o=%d, store_pending_o=%d)", load_pending_o, store_pending_o); |
`endif |
// Stall! |
stall_o = 1'b1; |
end |
end |
end |
|
`include "altor32_funcs.v" |
|
endmodule |
/rtl/sim/test_image.lst
0,0 → 1,4630
|
firmware.elf: file format elf32-or1k |
|
Sections: |
Idx Name Size VMA LMA File off Algn |
0 .text 00002fd8 10000000 10000000 00002000 2**2 |
CONTENTS, ALLOC, LOAD, READONLY, CODE |
1 .data 00000008 10002fd8 10002fd8 00004fd8 2**2 |
CONTENTS, ALLOC, LOAD, DATA |
2 .bss 00001030 10002fe0 10002fe0 00004fe0 2**2 |
ALLOC |
3 .debug_info 00002151 00000000 00000000 00004fe0 2**0 |
CONTENTS, READONLY, DEBUGGING |
4 .debug_abbrev 00000b63 00000000 00000000 00007131 2**0 |
CONTENTS, READONLY, DEBUGGING |
5 .debug_loc 00000fc6 00000000 00000000 00007c94 2**0 |
CONTENTS, READONLY, DEBUGGING |
6 .debug_aranges 00000140 00000000 00000000 00008c5a 2**0 |
CONTENTS, READONLY, DEBUGGING |
7 .debug_ranges 000000b8 00000000 00000000 00008d9a 2**0 |
CONTENTS, READONLY, DEBUGGING |
8 .debug_line 00000ad7 00000000 00000000 00008e52 2**0 |
CONTENTS, READONLY, DEBUGGING |
9 .debug_str 000006d5 00000000 00000000 00009929 2**0 |
CONTENTS, READONLY, DEBUGGING |
10 .comment 00000029 00000000 00000000 00009ffe 2**0 |
CONTENTS, READONLY |
11 .debug_frame 0000039c 00000000 00000000 0000a028 2**2 |
CONTENTS, READONLY, DEBUGGING |
|
Disassembly of section .text: |
|
10000000 <_start-0x100>: |
... |
|
10000100 <_start>: |
10000100: 18 80 10 00 l.movhi r4,0x1000 |
10000104: a8 24 40 00 l.ori r1,r4,0x4000 |
10000108: 18 80 10 00 l.movhi r4,0x1000 |
1000010c: a8 84 2f e0 l.ori r4,r4,0x2fe0 |
10000110: 18 a0 10 00 l.movhi r5,0x1000 |
10000114: a8 a5 40 10 l.ori r5,r5,0x4010 |
|
10000118 <BSS_CLEAR>: |
10000118: d4 04 00 00 l.sw 0(r4),r0 |
1000011c: e4 a4 28 00 l.sfleu r4,r5 |
10000120: 9c 84 00 04 l.addi r4,r4,4 |
10000124: 13 ff ff fd l.bf 10000118 <BSS_CLEAR> |
10000128: 15 00 00 00 l.nop 0x0 |
1000012c: 04 00 03 b5 l.jal 10001000 <main> |
10000130: 15 00 00 00 l.nop 0x0 |
... |
|
10000400 <vector_extint>: |
10000400: 24 00 00 00 l.rfe |
10000404: 15 00 00 00 l.nop 0x0 |
... |
10000ffc: 15 00 00 00 l.nop 0x0 |
|
10001000 <main>: |
int main(void) |
{ |
int res; |
|
// Setup printf to serial port |
printf_register(serial_putchar); |
10001000: 18 60 10 00 l.movhi r3,0x1000 |
|
//----------------------------------------------------------------- |
// main: |
//----------------------------------------------------------------- |
int main(void) |
{ |
10001004: d7 e1 4f fc l.sw -4(r1),r9 |
10001008: d7 e1 0f f8 l.sw -8(r1),r1 |
int res; |
|
// Setup printf to serial port |
printf_register(serial_putchar); |
1000100c: a8 63 1a 54 l.ori r3,r3,0x1a54 |
|
//----------------------------------------------------------------- |
// main: |
//----------------------------------------------------------------- |
int main(void) |
{ |
10001010: 9c 21 ff f8 l.addi r1,r1,-8 |
int res; |
|
// Setup printf to serial port |
printf_register(serial_putchar); |
10001014: 04 00 01 32 l.jal 100014dc <printf_register> |
|
// Run test |
res = test(); |
10001018: 04 00 03 35 l.jal 10001cec <test> |
static inline void exit(unsigned exit_code) |
{ |
volatile register char t1 asm ("r1") = exit_code; |
|
// No error? |
if (exit_code == 0) |
1000101c: bc 2b 00 00 l.sfnei r11,0 |
|
} |
|
static inline void exit(unsigned exit_code) |
{ |
volatile register char t1 asm ("r1") = exit_code; |
10001020: a5 6b 00 ff l.andi r11,r11,0xff |
10001024: a8 2b 00 00 l.ori r1,r11,0x0 |
|
// No error? |
if (exit_code == 0) |
10001028: 0c 00 00 06 l.bnf 10001040 <main+0x40> |
__asm__ __volatile__ ( "\t l.trap 0 "); |
} |
else |
{ |
// Invalid instruction! |
__asm__ __volatile__ ( "\t lf.add.s r0,r0,r0 "); |
1000102c: c8 00 00 00 lf.add.s r0,r0,r0 |
|
// Exit with result |
exit(res); |
} |
10001030: 9c 21 00 08 l.addi r1,r1,8 |
10001034: 85 21 ff fc l.lwz r9,-4(r1) |
10001038: 84 21 ff f8 l.lwz r1,-8(r1) |
1000103c: 44 00 48 00 l.jr r9 |
|
// No error? |
if (exit_code == 0) |
{ |
// Trap instruction |
__asm__ __volatile__ ( "\t l.trap 0 "); |
10001040: 21 00 00 00 l.trap 0x0 |
10001044: 03 ff ff fb l.j 10001030 <main+0x30> |
|
10001048 <exception_register_fault_handler>: |
static volatile int in_interrupt = 0; |
|
//----------------------------------------------------------------- |
// exception_register: |
//----------------------------------------------------------------- |
void exception_register_fault_handler(void (*func)(void)) { func_fault = func; } |
10001048: 18 80 10 00 l.movhi r4,0x1000 |
1000104c: d7 e1 0f fc l.sw -4(r1),r1 |
10001050: a8 84 2f f0 l.ori r4,r4,0x2ff0 |
10001054: 9c 21 ff fc l.addi r1,r1,-4 |
10001058: d4 04 18 00 l.sw 0(r4),r3 |
1000105c: 9c 21 00 04 l.addi r1,r1,4 |
10001060: 84 21 ff fc l.lwz r1,-4(r1) |
10001064: 44 00 48 00 l.jr r9 |
|
10001068 <exception_register_break_handler>: |
void exception_register_break_handler(void (*func)(void)) { func_break = func; } |
10001068: 18 80 10 00 l.movhi r4,0x1000 |
1000106c: d7 e1 0f fc l.sw -4(r1),r1 |
10001070: a8 84 2f ec l.ori r4,r4,0x2fec |
10001074: 9c 21 ff fc l.addi r1,r1,-4 |
10001078: d4 04 18 00 l.sw 0(r4),r3 |
1000107c: 9c 21 00 04 l.addi r1,r1,4 |
10001080: 84 21 ff fc l.lwz r1,-4(r1) |
10001084: 44 00 48 00 l.jr r9 |
|
10001088 <exception_register_extint_handler>: |
void exception_register_extint_handler(void (*func)(void)) { func_extint = func; } |
10001088: 18 80 10 00 l.movhi r4,0x1000 |
1000108c: d7 e1 0f fc l.sw -4(r1),r1 |
10001090: a8 84 2f e8 l.ori r4,r4,0x2fe8 |
10001094: 9c 21 ff fc l.addi r1,r1,-4 |
10001098: d4 04 18 00 l.sw 0(r4),r3 |
1000109c: 9c 21 00 04 l.addi r1,r1,4 |
100010a0: 84 21 ff fc l.lwz r1,-4(r1) |
100010a4: 44 00 48 00 l.jr r9 |
|
100010a8 <exception_register_syscall_handler>: |
void exception_register_syscall_handler(void (*func)(void)) { func_syscall = func; } |
100010a8: 18 80 10 00 l.movhi r4,0x1000 |
100010ac: d7 e1 0f fc l.sw -4(r1),r1 |
100010b0: a8 84 2f e4 l.ori r4,r4,0x2fe4 |
100010b4: 9c 21 ff fc l.addi r1,r1,-4 |
100010b8: d4 04 18 00 l.sw 0(r4),r3 |
100010bc: 9c 21 00 04 l.addi r1,r1,4 |
100010c0: 84 21 ff fc l.lwz r1,-4(r1) |
100010c4: 44 00 48 00 l.jr r9 |
|
100010c8 <cpu_handle_irq>: |
|
//----------------------------------------------------------------- |
// cpu_handle_irq: |
//----------------------------------------------------------------- |
void cpu_handle_irq(unsigned cause) |
{ |
100010c8: d7 e1 17 f4 l.sw -12(r1),r2 |
int recursive_int = (in_interrupt != 0); |
100010cc: 18 40 10 00 l.movhi r2,0x1000 |
|
in_interrupt = 1; |
100010d0: 9c 80 00 01 l.addi r4,r0,1 |
//----------------------------------------------------------------- |
// cpu_handle_irq: |
//----------------------------------------------------------------- |
void cpu_handle_irq(unsigned cause) |
{ |
int recursive_int = (in_interrupt != 0); |
100010d4: a8 42 2f e0 l.ori r2,r2,0x2fe0 |
|
//----------------------------------------------------------------- |
// cpu_handle_irq: |
//----------------------------------------------------------------- |
void cpu_handle_irq(unsigned cause) |
{ |
100010d8: d7 e1 77 f8 l.sw -8(r1),r14 |
100010dc: d7 e1 4f fc l.sw -4(r1),r9 |
100010e0: d7 e1 0f f0 l.sw -16(r1),r1 |
int recursive_int = (in_interrupt != 0); |
100010e4: 85 c2 00 00 l.lwz r14,0(r2) |
|
in_interrupt = 1; |
|
switch (cause) |
100010e8: bc 43 00 08 l.sfgtui r3,8 |
//----------------------------------------------------------------- |
void cpu_handle_irq(unsigned cause) |
{ |
int recursive_int = (in_interrupt != 0); |
|
in_interrupt = 1; |
100010ec: d4 02 20 00 l.sw 0(r2),r4 |
|
//----------------------------------------------------------------- |
// cpu_handle_irq: |
//----------------------------------------------------------------- |
void cpu_handle_irq(unsigned cause) |
{ |
100010f0: 9c 21 ff e4 l.addi r1,r1,-28 |
int recursive_int = (in_interrupt != 0); |
|
in_interrupt = 1; |
|
switch (cause) |
100010f4: 10 00 00 71 l.bf 100012b8 <cpu_handle_irq+0x1f0> |
100010f8: 18 80 10 00 l.movhi r4,0x1000 |
100010fc: b8 63 00 02 l.slli r3,r3,0x2 |
10001100: a8 84 2b 00 l.ori r4,r4,0x2b00 |
10001104: e0 63 20 00 l.add r3,r3,r4 |
10001108: 84 63 00 00 l.lwz r3,0(r3) |
1000110c: 44 00 18 00 l.jr r3 |
case EXCEPTION_DIV: |
panic("DIV!"); |
break; |
|
case EXCEPTION_UDIV: |
panic("UDIV!"); |
10001110: 18 60 10 00 l.movhi r3,0x1000 |
10001114: a8 63 2c e4 l.ori r3,r3,0x2ce4 |
10001118: d4 01 18 00 l.sw 0(r1),r3 |
1000111c: 18 60 10 00 l.movhi r3,0x1000 |
10001120: a8 63 2c 9a l.ori r3,r3,0x2c9a |
10001124: d4 01 18 04 l.sw 4(r1),r3 |
10001128: 9c 60 00 6e l.addi r3,r0,110 |
break; |
|
default: |
panic("UNKNOWN"); |
1000112c: d4 01 18 08 l.sw 8(r1),r3 |
10001130: 18 60 10 00 l.movhi r3,0x1000 |
10001134: a8 63 2c 74 l.ori r3,r3,0x2c74 |
10001138: 04 00 02 2b l.jal 100019e4 <printf> |
|
} |
|
static inline void exit(unsigned exit_code) |
{ |
volatile register char t1 asm ("r1") = exit_code; |
1000113c: 9c 20 00 01 l.addi r1,r0,1 |
__asm__ __volatile__ ( "\t l.trap 0 "); |
} |
else |
{ |
// Invalid instruction! |
__asm__ __volatile__ ( "\t lf.add.s r0,r0,r0 "); |
10001140: c8 00 00 00 lf.add.s r0,r0,r0 |
break; |
} |
|
assert(recursive_int == 0); |
10001144: bc 0e 00 00 l.sfeqi r14,0 |
10001148: 10 00 00 0e l.bf 10001180 <cpu_handle_irq+0xb8> |
1000114c: 18 60 10 00 l.movhi r3,0x1000 |
10001150: a8 63 2c f6 l.ori r3,r3,0x2cf6 |
10001154: d4 01 18 00 l.sw 0(r1),r3 |
10001158: 18 60 10 00 l.movhi r3,0x1000 |
1000115c: a8 63 2c 9a l.ori r3,r3,0x2c9a |
10001160: d4 01 18 04 l.sw 4(r1),r3 |
10001164: 9c 60 00 76 l.addi r3,r0,118 |
10001168: d4 01 18 08 l.sw 8(r1),r3 |
1000116c: 18 60 10 00 l.movhi r3,0x1000 |
10001170: a8 63 2c 74 l.ori r3,r3,0x2c74 |
10001174: 04 00 02 1c l.jal 100019e4 <printf> |
|
} |
|
static inline void exit(unsigned exit_code) |
{ |
volatile register char t1 asm ("r1") = exit_code; |
10001178: 9c 20 00 01 l.addi r1,r0,1 |
__asm__ __volatile__ ( "\t l.trap 0 "); |
} |
else |
{ |
// Invalid instruction! |
__asm__ __volatile__ ( "\t lf.add.s r0,r0,r0 "); |
1000117c: c8 00 00 00 lf.add.s r0,r0,r0 |
|
in_interrupt = 0; |
10001180: 9c 60 00 00 l.addi r3,r0,0 |
10001184: d4 02 18 00 l.sw 0(r2),r3 |
} |
10001188: 9c 21 00 1c l.addi r1,r1,28 |
1000118c: 85 21 ff fc l.lwz r9,-4(r1) |
10001190: 84 21 ff f0 l.lwz r1,-16(r1) |
10001194: 84 41 ff f4 l.lwz r2,-12(r1) |
10001198: 85 c1 ff f8 l.lwz r14,-8(r1) |
1000119c: 44 00 48 00 l.jr r9 |
in_interrupt = 1; |
|
switch (cause) |
{ |
case EXCEPTION_SYSCALL: |
if (func_syscall) |
100011a0: 18 60 10 00 l.movhi r3,0x1000 |
100011a4: a8 63 2f e4 l.ori r3,r3,0x2fe4 |
100011a8: 84 63 00 00 l.lwz r3,0(r3) |
100011ac: bc 03 00 00 l.sfeqi r3,0 |
100011b0: 10 00 00 4a l.bf 100012d8 <cpu_handle_irq+0x210> |
panic("EXT_INT!"); |
break; |
|
case EXCEPTION_FAULT: |
if (func_fault) |
func_fault(); |
100011b4: 48 00 18 00 l.jalr r3 |
100011b8: 03 ff ff e3 l.j 10001144 <cpu_handle_irq+0x7c> |
else |
panic("SYSCALL!"); |
break; |
|
case EXCEPTION_BREAK: |
if (func_break) |
100011bc: 18 60 10 00 l.movhi r3,0x1000 |
100011c0: a8 63 2f ec l.ori r3,r3,0x2fec |
100011c4: 84 63 00 00 l.lwz r3,0(r3) |
100011c8: bc 03 00 00 l.sfeqi r3,0 |
100011cc: 0f ff ff fa l.bnf 100011b4 <cpu_handle_irq+0xec> |
func_break(); |
else |
panic("BREAK!"); |
100011d0: 18 60 10 00 l.movhi r3,0x1000 |
100011d4: a8 63 2c b0 l.ori r3,r3,0x2cb0 |
100011d8: d4 01 18 00 l.sw 0(r1),r3 |
100011dc: 18 60 10 00 l.movhi r3,0x1000 |
100011e0: a8 63 2c 9a l.ori r3,r3,0x2c9a |
100011e4: d4 01 18 04 l.sw 4(r1),r3 |
100011e8: 9c 60 00 50 l.addi r3,r0,80 |
100011ec: 03 ff ff d0 l.j 1000112c <cpu_handle_irq+0x64> |
break; |
|
case EXCEPTION_EXTINT: |
if (func_extint) |
100011f0: 18 60 10 00 l.movhi r3,0x1000 |
100011f4: a8 63 2f e8 l.ori r3,r3,0x2fe8 |
100011f8: 84 63 00 00 l.lwz r3,0(r3) |
100011fc: bc 03 00 00 l.sfeqi r3,0 |
10001200: 0f ff ff ed l.bnf 100011b4 <cpu_handle_irq+0xec> |
func_extint(); |
else |
panic("EXT_INT!"); |
10001204: 18 60 10 00 l.movhi r3,0x1000 |
10001208: a8 63 2c b9 l.ori r3,r3,0x2cb9 |
1000120c: d4 01 18 00 l.sw 0(r1),r3 |
10001210: 18 60 10 00 l.movhi r3,0x1000 |
10001214: a8 63 2c 9a l.ori r3,r3,0x2c9a |
10001218: d4 01 18 04 l.sw 4(r1),r3 |
1000121c: 9c 60 00 57 l.addi r3,r0,87 |
10001220: 03 ff ff c3 l.j 1000112c <cpu_handle_irq+0x64> |
break; |
|
case EXCEPTION_FAULT: |
if (func_fault) |
10001224: 18 60 10 00 l.movhi r3,0x1000 |
10001228: a8 63 2f f0 l.ori r3,r3,0x2ff0 |
1000122c: 84 63 00 00 l.lwz r3,0(r3) |
10001230: bc 03 00 00 l.sfeqi r3,0 |
10001234: 0f ff ff e0 l.bnf 100011b4 <cpu_handle_irq+0xec> |
func_fault(); |
else |
panic("FAULT"); |
10001238: 18 60 10 00 l.movhi r3,0x1000 |
1000123c: a8 63 2c c4 l.ori r3,r3,0x2cc4 |
10001240: d4 01 18 00 l.sw 0(r1),r3 |
10001244: 18 60 10 00 l.movhi r3,0x1000 |
10001248: a8 63 2c 9a l.ori r3,r3,0x2c9a |
1000124c: d4 01 18 04 l.sw 4(r1),r3 |
10001250: 9c 60 00 5e l.addi r3,r0,94 |
10001254: 03 ff ff b6 l.j 1000112c <cpu_handle_irq+0x64> |
break; |
|
case EXCEPTION_MULT: |
panic("MULT!"); |
10001258: 18 60 10 00 l.movhi r3,0x1000 |
1000125c: a8 63 2c cc l.ori r3,r3,0x2ccc |
10001260: d4 01 18 00 l.sw 0(r1),r3 |
10001264: 18 60 10 00 l.movhi r3,0x1000 |
10001268: a8 63 2c 9a l.ori r3,r3,0x2c9a |
1000126c: d4 01 18 04 l.sw 4(r1),r3 |
10001270: 9c 60 00 62 l.addi r3,r0,98 |
10001274: 03 ff ff ae l.j 1000112c <cpu_handle_irq+0x64> |
break; |
|
case EXCEPTION_UMULT: |
panic("UMULT!"); |
10001278: 18 60 10 00 l.movhi r3,0x1000 |
1000127c: a8 63 2c d4 l.ori r3,r3,0x2cd4 |
10001280: d4 01 18 00 l.sw 0(r1),r3 |
10001284: 18 60 10 00 l.movhi r3,0x1000 |
10001288: a8 63 2c 9a l.ori r3,r3,0x2c9a |
1000128c: d4 01 18 04 l.sw 4(r1),r3 |
10001290: 9c 60 00 66 l.addi r3,r0,102 |
10001294: 03 ff ff a6 l.j 1000112c <cpu_handle_irq+0x64> |
break; |
|
case EXCEPTION_DIV: |
panic("DIV!"); |
10001298: 18 60 10 00 l.movhi r3,0x1000 |
1000129c: a8 63 2c dd l.ori r3,r3,0x2cdd |
100012a0: d4 01 18 00 l.sw 0(r1),r3 |
100012a4: 18 60 10 00 l.movhi r3,0x1000 |
100012a8: a8 63 2c 9a l.ori r3,r3,0x2c9a |
100012ac: d4 01 18 04 l.sw 4(r1),r3 |
100012b0: 9c 60 00 6a l.addi r3,r0,106 |
100012b4: 03 ff ff 9e l.j 1000112c <cpu_handle_irq+0x64> |
case EXCEPTION_UDIV: |
panic("UDIV!"); |
break; |
|
default: |
panic("UNKNOWN"); |
100012b8: 18 60 10 00 l.movhi r3,0x1000 |
100012bc: a8 63 2c ec l.ori r3,r3,0x2cec |
100012c0: d4 01 18 00 l.sw 0(r1),r3 |
100012c4: 18 60 10 00 l.movhi r3,0x1000 |
100012c8: a8 63 2c 9a l.ori r3,r3,0x2c9a |
100012cc: d4 01 18 04 l.sw 4(r1),r3 |
100012d0: 9c 60 00 72 l.addi r3,r0,114 |
100012d4: 03 ff ff 96 l.j 1000112c <cpu_handle_irq+0x64> |
{ |
case EXCEPTION_SYSCALL: |
if (func_syscall) |
func_syscall(); |
else |
panic("SYSCALL!"); |
100012d8: 18 60 10 00 l.movhi r3,0x1000 |
100012dc: a8 63 2c 8f l.ori r3,r3,0x2c8f |
100012e0: d4 01 18 00 l.sw 0(r1),r3 |
100012e4: 18 60 10 00 l.movhi r3,0x1000 |
100012e8: a8 63 2c 9a l.ori r3,r3,0x2c9a |
100012ec: d4 01 18 04 l.sw 4(r1),r3 |
100012f0: 9c 60 00 49 l.addi r3,r0,73 |
100012f4: 03 ff ff 8e l.j 1000112c <cpu_handle_irq+0x64> |
|
100012f8 <outnum.isra.1>: |
static void outnum( struct vbuf *buf, const long n, const long base, params_t *par) |
{ |
char* cp; |
int negative; |
char outbuf[32]; |
const char udigits[] = "0123456789ABCDEF"; |
100012f8: 18 e0 38 39 l.movhi r7,0x3839 |
/* This routine moves a number to the output buffer */ |
/* as directed by the padding and positioning flags. */ |
/* */ |
//---------------------------------------------------- |
#if defined PRINTF_DEC_PRINT || defined PRINTF_HEX_PRINT |
static void outnum( struct vbuf *buf, const long n, const long base, params_t *par) |
100012fc: d7 e1 17 dc l.sw -36(r1),r2 |
{ |
char* cp; |
int negative; |
char outbuf[32]; |
const char udigits[] = "0123456789ABCDEF"; |
10001300: a9 07 41 42 l.ori r8,r7,0x4142 |
/* This routine moves a number to the output buffer */ |
/* as directed by the padding and positioning flags. */ |
/* */ |
//---------------------------------------------------- |
#if defined PRINTF_DEC_PRINT || defined PRINTF_HEX_PRINT |
static void outnum( struct vbuf *buf, const long n, const long base, params_t *par) |
10001304: d7 e1 a7 e8 l.sw -24(r1),r20 |
10001308: d7 e1 b7 ec l.sw -20(r1),r22 |
1000130c: d7 e1 4f fc l.sw -4(r1),r9 |
10001310: d7 e1 0f d8 l.sw -40(r1),r1 |
10001314: d7 e1 77 e0 l.sw -32(r1),r14 |
10001318: d7 e1 97 e4 l.sw -28(r1),r18 |
1000131c: d7 e1 c7 f0 l.sw -16(r1),r24 |
10001320: d7 e1 d7 f4 l.sw -12(r1),r26 |
10001324: d7 e1 e7 f8 l.sw -8(r1),r28 |
{ |
char* cp; |
int negative; |
char outbuf[32]; |
const char udigits[] = "0123456789ABCDEF"; |
10001328: 18 40 34 35 l.movhi r2,0x3435 |
/* This routine moves a number to the output buffer */ |
/* as directed by the padding and positioning flags. */ |
/* */ |
//---------------------------------------------------- |
#if defined PRINTF_DEC_PRINT || defined PRINTF_HEX_PRINT |
static void outnum( struct vbuf *buf, const long n, const long base, params_t *par) |
1000132c: 9c 21 ff 90 l.addi r1,r1,-112 |
const char *digits; |
unsigned long num; |
int count; |
|
/* Check if number is negative */ |
if (base == 10 && n < 0L) { |
10001330: ac c4 00 0a l.xori r6,r4,10 |
static void outnum( struct vbuf *buf, const long n, const long base, params_t *par) |
{ |
char* cp; |
int negative; |
char outbuf[32]; |
const char udigits[] = "0123456789ABCDEF"; |
10001334: a8 42 36 37 l.ori r2,r2,0x3637 |
10001338: d4 01 40 08 l.sw 8(r1),r8 |
1000133c: 19 00 43 44 l.movhi r8,0x4344 |
/* This routine moves a number to the output buffer */ |
/* as directed by the padding and positioning flags. */ |
/* */ |
//---------------------------------------------------- |
#if defined PRINTF_DEC_PRINT || defined PRINTF_HEX_PRINT |
static void outnum( struct vbuf *buf, const long n, const long base, params_t *par) |
10001340: aa 84 00 00 l.ori r20,r4,0x0 |
{ |
char* cp; |
int negative; |
char outbuf[32]; |
const char udigits[] = "0123456789ABCDEF"; |
10001344: a9 08 45 46 l.ori r8,r8,0x4546 |
const char *digits; |
unsigned long num; |
int count; |
|
/* Check if number is negative */ |
if (base == 10 && n < 0L) { |
10001348: e1 60 30 02 l.sub r11,r0,r6 |
static void outnum( struct vbuf *buf, const long n, const long base, params_t *par) |
{ |
char* cp; |
int negative; |
char outbuf[32]; |
const char udigits[] = "0123456789ABCDEF"; |
1000134c: 18 80 30 31 l.movhi r4,0x3031 |
10001350: d4 01 10 04 l.sw 4(r1),r2 |
const char ldigits[] = "0123456789abcdef"; |
10001354: d4 01 10 18 l.sw 24(r1),r2 |
10001358: 18 40 63 64 l.movhi r2,0x6364 |
static void outnum( struct vbuf *buf, const long n, const long base, params_t *par) |
{ |
char* cp; |
int negative; |
char outbuf[32]; |
const char udigits[] = "0123456789ABCDEF"; |
1000135c: a8 84 32 33 l.ori r4,r4,0x3233 |
const char ldigits[] = "0123456789abcdef"; |
10001360: a8 e7 61 62 l.ori r7,r7,0x6162 |
const char *digits; |
unsigned long num; |
int count; |
|
/* Check if number is negative */ |
if (base == 10 && n < 0L) { |
10001364: e0 cb 30 04 l.or r6,r11,r6 |
static void outnum( struct vbuf *buf, const long n, const long base, params_t *par) |
{ |
char* cp; |
int negative; |
char outbuf[32]; |
const char udigits[] = "0123456789ABCDEF"; |
10001368: d4 01 40 0c l.sw 12(r1),r8 |
const char ldigits[] = "0123456789abcdef"; |
1000136c: a8 42 65 66 l.ori r2,r2,0x6566 |
static void outnum( struct vbuf *buf, const long n, const long base, params_t *par) |
{ |
char* cp; |
int negative; |
char outbuf[32]; |
const char udigits[] = "0123456789ABCDEF"; |
10001370: 9d 00 00 00 l.addi r8,r0,0 |
10001374: d4 01 20 00 l.sw 0(r1),r4 |
10001378: d8 01 40 10 l.sb 16(r1),r8 |
const char ldigits[] = "0123456789abcdef"; |
1000137c: d4 01 20 14 l.sw 20(r1),r4 |
10001380: d4 01 38 1c l.sw 28(r1),r7 |
10001384: d4 01 10 20 l.sw 32(r1),r2 |
10001388: d8 01 40 24 l.sb 36(r1),r8 |
const char *digits; |
unsigned long num; |
int count; |
|
/* Check if number is negative */ |
if (base == 10 && n < 0L) { |
1000138c: bd 86 00 00 l.sfltsi r6,0 |
/* This routine moves a number to the output buffer */ |
/* as directed by the padding and positioning flags. */ |
/* */ |
//---------------------------------------------------- |
#if defined PRINTF_DEC_PRINT || defined PRINTF_HEX_PRINT |
static void outnum( struct vbuf *buf, const long n, const long base, params_t *par) |
10001390: aa c5 00 00 l.ori r22,r5,0x0 |
const char *digits; |
unsigned long num; |
int count; |
|
/* Check if number is negative */ |
if (base == 10 && n < 0L) { |
10001394: 10 00 00 03 l.bf 100013a0 <outnum.isra.1+0xa8> |
10001398: bd 63 00 00 l.sfgesi r3,0 |
1000139c: 0c 00 00 4d l.bnf 100014d0 <outnum.isra.1+0x1d8> |
negative = 1; |
num = -(n); |
} |
else{ |
num = (n); |
100013a0: a8 43 00 00 l.ori r2,r3,0x0 |
negative = 0; |
100013a4: 9f 80 00 00 l.addi r28,r0,0 |
} |
|
if (par->uppercase) |
100013a8: 84 76 00 18 l.lwz r3,24(r22) |
digits = udigits; |
100013ac: ab 41 00 00 l.ori r26,r1,0x0 |
else{ |
num = (n); |
negative = 0; |
} |
|
if (par->uppercase) |
100013b0: bc 03 00 00 l.sfeqi r3,0 |
100013b4: 0c 00 00 02 l.bnf 100013bc <outnum.isra.1+0xc4> |
digits = udigits; |
else |
digits = ldigits; |
100013b8: 9f 41 00 14 l.addi r26,r1,20 |
100013bc: 9f 01 00 28 l.addi r24,r1,40 |
100013c0: a9 d8 00 00 l.ori r14,r24,0x0 |
100013c4: 00 00 00 02 l.j 100013cc <outnum.isra.1+0xd4> |
100013c8: a9 d2 00 00 l.ori r14,r18,0x0 |
|
/* Build number (backwards) in outbuf */ |
cp = outbuf; |
do { |
*cp++ = digits[(int)(num % base)]; |
100013cc: a8 62 00 00 l.ori r3,r2,0x0 |
100013d0: a8 94 00 00 l.ori r4,r20,0x0 |
/* This routine moves a number to the output buffer */ |
/* as directed by the padding and positioning flags. */ |
/* */ |
//---------------------------------------------------- |
#if defined PRINTF_DEC_PRINT || defined PRINTF_HEX_PRINT |
static void outnum( struct vbuf *buf, const long n, const long base, params_t *par) |
100013d4: 9e 4e 00 01 l.addi r18,r14,1 |
digits = ldigits; |
|
/* Build number (backwards) in outbuf */ |
cp = outbuf; |
do { |
*cp++ = digits[(int)(num % base)]; |
100013d8: 04 00 05 52 l.jal 10002920 <__umodsi3> |
100013dc: e1 7a 58 00 l.add r11,r26,r11 |
} while ((num /= base) > 0); |
100013e0: a8 62 00 00 l.ori r3,r2,0x0 |
digits = ldigits; |
|
/* Build number (backwards) in outbuf */ |
cp = outbuf; |
do { |
*cp++ = digits[(int)(num % base)]; |
100013e4: 8d 6b 00 00 l.lbz r11,0(r11) |
} while ((num /= base) > 0); |
100013e8: a8 94 00 00 l.ori r4,r20,0x0 |
digits = ldigits; |
|
/* Build number (backwards) in outbuf */ |
cp = outbuf; |
do { |
*cp++ = digits[(int)(num % base)]; |
100013ec: d8 0e 58 00 l.sb 0(r14),r11 |
} while ((num /= base) > 0); |
100013f0: 04 00 05 43 l.jal 100028fc <__udivsi3> |
100013f4: bc 0b 00 00 l.sfeqi r11,0 |
100013f8: a8 4b 00 00 l.ori r2,r11,0x0 |
100013fc: 0f ff ff f3 l.bnf 100013c8 <outnum.isra.1+0xd0> |
if (negative) |
10001400: bc 1c 00 00 l.sfeqi r28,0 |
10001404: 10 00 00 04 l.bf 10001414 <outnum.isra.1+0x11c> |
*cp++ = '-'; |
10001408: 9c 40 00 2d l.addi r2,r0,45 |
1000140c: 9e 4e 00 02 l.addi r18,r14,2 |
10001410: d8 0e 10 01 l.sb 1(r14),r2 |
*cp-- = 0; |
10001414: 9d 00 00 00 l.addi r8,r0,0 |
10001418: 9d d2 ff ff l.addi r14,r18,-1 |
1000141c: d8 12 40 00 l.sb 0(r18),r8 |
const char * s; |
|
if(!str) |
return 0; |
|
for(s = str; *s; ++ s) |
10001420: 90 81 00 28 l.lbs r4,40(r1) |
10001424: bc 04 00 00 l.sfeqi r4,0 |
10001428: 10 00 00 08 l.bf 10001448 <outnum.isra.1+0x150> |
1000142c: 9c 41 00 29 l.addi r2,r1,41 |
10001430: a8 82 00 00 l.ori r4,r2,0x0 |
10001434: 9c 42 00 01 l.addi r2,r2,1 |
10001438: 90 62 ff ff l.lbs r3,-1(r2) |
1000143c: bc 03 00 00 l.sfeqi r3,0 |
10001440: 0f ff ff fc l.bnf 10001430 <outnum.isra.1+0x138> |
10001444: e0 84 c0 02 l.sub r4,r4,r24 |
*cp++ = '-'; |
*cp-- = 0; |
|
/* Move the converted number to the buffer and */ |
/* add in the padding where needed. */ |
par->len = strlen(outbuf); |
10001448: d4 16 20 00 l.sw 0(r22),r4 |
#ifdef PRINTF_ENABLE_PADDING |
padding(buf, !(par->left_flag), par); |
#endif |
count = 0; |
while (cp >= outbuf && count++ < par->max_len) |
1000144c: e4 6e c0 00 l.sfgeu r14,r24 |
10001450: 0c 00 00 14 l.bnf 100014a0 <outnum.isra.1+0x1a8> |
10001454: 84 56 00 1c l.lwz r2,28(r22) |
10001458: bd a2 00 00 l.sflesi r2,0 |
1000145c: 10 00 00 11 l.bf 100014a0 <outnum.isra.1+0x1a8> |
10001460: 1a 80 10 00 l.movhi r20,0x1000 |
/* This routine moves a number to the output buffer */ |
/* as directed by the padding and positioning flags. */ |
/* */ |
//---------------------------------------------------- |
#if defined PRINTF_DEC_PRINT || defined PRINTF_HEX_PRINT |
static void outnum( struct vbuf *buf, const long n, const long base, params_t *par) |
10001464: e2 52 c0 02 l.sub r18,r18,r24 |
par->len = strlen(outbuf); |
#ifdef PRINTF_ENABLE_PADDING |
padding(buf, !(par->left_flag), par); |
#endif |
count = 0; |
while (cp >= outbuf && count++ < par->max_len) |
10001468: 9c 40 00 01 l.addi r2,r0,1 |
1000146c: aa 94 2f f4 l.ori r20,r20,0x2ff4 |
10001470: 00 00 00 05 l.j 10001484 <outnum.isra.1+0x18c> |
10001474: 84 96 00 1c l.lwz r4,28(r22) |
10001478: e5 a4 10 00 l.sfles r4,r2 |
1000147c: a8 43 00 00 l.ori r2,r3,0x0 |
10001480: 10 00 00 08 l.bf 100014a0 <outnum.isra.1+0x1a8> |
vbuf_putchar(buf, *cp--); |
10001484: 90 6e 00 00 l.lbs r3,0(r14) |
10001488: 85 74 00 00 l.lwz r11,0(r20) |
1000148c: 9d ce ff ff l.addi r14,r14,-1 |
10001490: 48 00 58 00 l.jalr r11 |
par->len = strlen(outbuf); |
#ifdef PRINTF_ENABLE_PADDING |
padding(buf, !(par->left_flag), par); |
#endif |
count = 0; |
while (cp >= outbuf && count++ < par->max_len) |
10001494: e4 02 90 00 l.sfeq r2,r18 |
10001498: 9c 62 00 01 l.addi r3,r2,1 |
1000149c: 0f ff ff f6 l.bnf 10001474 <outnum.isra.1+0x17c> |
vbuf_putchar(buf, *cp--); |
#ifdef PRINTF_ENABLE_PADDING |
padding(buf, par->left_flag, par); |
#endif |
} |
100014a0: 9c 21 00 70 l.addi r1,r1,112 |
100014a4: 85 21 ff fc l.lwz r9,-4(r1) |
100014a8: 84 21 ff d8 l.lwz r1,-40(r1) |
100014ac: 84 41 ff dc l.lwz r2,-36(r1) |
100014b0: 85 c1 ff e0 l.lwz r14,-32(r1) |
100014b4: 86 41 ff e4 l.lwz r18,-28(r1) |
100014b8: 86 81 ff e8 l.lwz r20,-24(r1) |
100014bc: 86 c1 ff ec l.lwz r22,-20(r1) |
100014c0: 87 01 ff f0 l.lwz r24,-16(r1) |
100014c4: 87 41 ff f4 l.lwz r26,-12(r1) |
100014c8: 87 81 ff f8 l.lwz r28,-8(r1) |
100014cc: 44 00 48 00 l.jr r9 |
int count; |
|
/* Check if number is negative */ |
if (base == 10 && n < 0L) { |
negative = 1; |
num = -(n); |
100014d0: e0 40 18 02 l.sub r2,r0,r3 |
unsigned long num; |
int count; |
|
/* Check if number is negative */ |
if (base == 10 && n < 0L) { |
negative = 1; |
100014d4: 9f 80 00 01 l.addi r28,r0,1 |
100014d8: 03 ff ff b4 l.j 100013a8 <outnum.isra.1+0xb0> |
|
100014dc <printf_register>: |
//---------------------------------------------------- |
// printf_register: Assign printf output function |
//---------------------------------------------------- |
void printf_register(FP_OUTCHAR f) |
{ |
_stdout = f; |
100014dc: 18 80 10 00 l.movhi r4,0x1000 |
} |
//---------------------------------------------------- |
// printf_register: Assign printf output function |
//---------------------------------------------------- |
void printf_register(FP_OUTCHAR f) |
{ |
100014e0: d7 e1 0f fc l.sw -4(r1),r1 |
_stdout = f; |
100014e4: a8 84 2f f4 l.ori r4,r4,0x2ff4 |
} |
//---------------------------------------------------- |
// printf_register: Assign printf output function |
//---------------------------------------------------- |
void printf_register(FP_OUTCHAR f) |
{ |
100014e8: 9c 21 ff fc l.addi r1,r1,-4 |
_stdout = f; |
100014ec: d4 04 18 00 l.sw 0(r4),r3 |
} |
100014f0: 9c 21 00 04 l.addi r1,r1,4 |
100014f4: 84 21 ff fc l.lwz r1,-4(r1) |
100014f8: 44 00 48 00 l.jr r9 |
|
100014fc <puts>: |
#endif |
//---------------------------------------------------- |
// puts: |
//---------------------------------------------------- |
int puts( const char * str ) |
{ |
100014fc: d7 e1 77 f8 l.sw -8(r1),r14 |
if (!_stdout) |
10001500: 19 c0 10 00 l.movhi r14,0x1000 |
#endif |
//---------------------------------------------------- |
// puts: |
//---------------------------------------------------- |
int puts( const char * str ) |
{ |
10001504: d7 e1 17 f4 l.sw -12(r1),r2 |
if (!_stdout) |
10001508: a9 ce 2f f4 l.ori r14,r14,0x2ff4 |
#endif |
//---------------------------------------------------- |
// puts: |
//---------------------------------------------------- |
int puts( const char * str ) |
{ |
1000150c: d7 e1 4f fc l.sw -4(r1),r9 |
if (!_stdout) |
10001510: 85 6e 00 00 l.lwz r11,0(r14) |
#endif |
//---------------------------------------------------- |
// puts: |
//---------------------------------------------------- |
int puts( const char * str ) |
{ |
10001514: d7 e1 0f f0 l.sw -16(r1),r1 |
if (!_stdout) |
10001518: bc 0b 00 00 l.sfeqi r11,0 |
#endif |
//---------------------------------------------------- |
// puts: |
//---------------------------------------------------- |
int puts( const char * str ) |
{ |
1000151c: 9c 21 ff f0 l.addi r1,r1,-16 |
10001520: a8 43 00 00 l.ori r2,r3,0x0 |
if (!_stdout) |
10001524: 10 00 00 12 l.bf 1000156c <puts+0x70> |
return -1; |
|
while (*str) |
10001528: 90 63 00 00 l.lbs r3,0(r3) |
1000152c: bc 03 00 00 l.sfeqi r3,0 |
10001530: 10 00 00 07 l.bf 1000154c <puts+0x50> |
_stdout(*str++); |
10001534: 9c 42 00 01 l.addi r2,r2,1 |
10001538: 48 00 58 00 l.jalr r11 |
int puts( const char * str ) |
{ |
if (!_stdout) |
return -1; |
|
while (*str) |
1000153c: 90 62 00 00 l.lbs r3,0(r2) |
10001540: bc 03 00 00 l.sfeqi r3,0 |
10001544: 85 6e 00 00 l.lwz r11,0(r14) |
10001548: 0f ff ff fb l.bnf 10001534 <puts+0x38> |
_stdout(*str++); |
|
return _stdout('\n'); |
1000154c: 9c 60 00 0a l.addi r3,r0,10 |
10001550: 48 00 58 00 l.jalr r11 |
} |
10001554: 9c 21 00 10 l.addi r1,r1,16 |
10001558: 85 21 ff fc l.lwz r9,-4(r1) |
1000155c: 84 21 ff f0 l.lwz r1,-16(r1) |
10001560: 84 41 ff f4 l.lwz r2,-12(r1) |
10001564: 85 c1 ff f8 l.lwz r14,-8(r1) |
10001568: 44 00 48 00 l.jr r9 |
// puts: |
//---------------------------------------------------- |
int puts( const char * str ) |
{ |
if (!_stdout) |
return -1; |
1000156c: 9d 60 ff ff l.addi r11,r0,-1 |
10001570: 03 ff ff f9 l.j 10001554 <puts+0x58> |
|
10001574 <putchar>: |
} |
//---------------------------------------------------- |
// putchar: |
//---------------------------------------------------- |
int putchar( int c ) |
{ |
10001574: d7 e1 17 f8 l.sw -8(r1),r2 |
10001578: a8 43 00 00 l.ori r2,r3,0x0 |
if (!_stdout) |
1000157c: 18 60 10 00 l.movhi r3,0x1000 |
} |
//---------------------------------------------------- |
// putchar: |
//---------------------------------------------------- |
int putchar( int c ) |
{ |
10001580: d7 e1 4f fc l.sw -4(r1),r9 |
if (!_stdout) |
10001584: a8 63 2f f4 l.ori r3,r3,0x2ff4 |
} |
//---------------------------------------------------- |
// putchar: |
//---------------------------------------------------- |
int putchar( int c ) |
{ |
10001588: d7 e1 0f f4 l.sw -12(r1),r1 |
if (!_stdout) |
1000158c: 85 63 00 00 l.lwz r11,0(r3) |
} |
//---------------------------------------------------- |
// putchar: |
//---------------------------------------------------- |
int putchar( int c ) |
{ |
10001590: 9c 21 ff f4 l.addi r1,r1,-12 |
if (!_stdout) |
10001594: bc 0b 00 00 l.sfeqi r11,0 |
10001598: 10 00 00 0a l.bf 100015c0 <putchar+0x4c> |
return -1; |
|
_stdout((char)c); |
1000159c: b8 62 00 18 l.slli r3,r2,0x18 |
100015a0: b8 63 00 98 l.srai r3,r3,0x18 |
100015a4: 48 00 58 00 l.jalr r11 |
|
return c; |
100015a8: a9 62 00 00 l.ori r11,r2,0x0 |
} |
100015ac: 9c 21 00 0c l.addi r1,r1,12 |
100015b0: 85 21 ff fc l.lwz r9,-4(r1) |
100015b4: 84 21 ff f4 l.lwz r1,-12(r1) |
100015b8: 84 41 ff f8 l.lwz r2,-8(r1) |
100015bc: 44 00 48 00 l.jr r9 |
// putchar: |
//---------------------------------------------------- |
int putchar( int c ) |
{ |
if (!_stdout) |
return -1; |
100015c0: 9d 60 ff ff l.addi r11,r0,-1 |
100015c4: 03 ff ff fa l.j 100015ac <putchar+0x38> |
|
100015c8 <vbuf_printf>: |
/* added easily by following the examples shown for */ |
/* the supported formats. */ |
/* */ |
//---------------------------------------------------- |
int vbuf_printf(struct vbuf *buf, const char* ctrl1, va_list argp) |
{ |
100015c8: d7 e1 97 e0 l.sw -32(r1),r18 |
100015cc: d7 e1 f7 f8 l.sw -8(r1),r30 |
100015d0: d7 e1 4f fc l.sw -4(r1),r9 |
100015d4: d7 e1 0f d4 l.sw -44(r1),r1 |
100015d8: d7 e1 17 d8 l.sw -40(r1),r2 |
100015dc: d7 e1 77 dc l.sw -36(r1),r14 |
100015e0: d7 e1 a7 e4 l.sw -28(r1),r20 |
100015e4: d7 e1 b7 e8 l.sw -24(r1),r22 |
100015e8: d7 e1 c7 ec l.sw -20(r1),r24 |
100015ec: d7 e1 d7 f0 l.sw -16(r1),r26 |
100015f0: d7 e1 e7 f4 l.sw -12(r1),r28 |
100015f4: ab c4 00 00 l.ori r30,r4,0x0 |
params_t par; |
|
char ch; |
char* ctrl = (char*)ctrl1; |
|
for ( ; *ctrl; ctrl++) |
100015f8: 90 64 00 00 l.lbs r3,0(r4) |
100015fc: bc 23 00 00 l.sfnei r3,0 |
/* added easily by following the examples shown for */ |
/* the supported formats. */ |
/* */ |
//---------------------------------------------------- |
int vbuf_printf(struct vbuf *buf, const char* ctrl1, va_list argp) |
{ |
10001600: 9c 21 ff b4 l.addi r1,r1,-76 |
10001604: aa 45 00 00 l.ori r18,r5,0x0 |
params_t par; |
|
char ch; |
char* ctrl = (char*)ctrl1; |
|
for ( ; *ctrl; ctrl++) |
10001608: 0c 00 00 77 l.bnf 100017e4 <vbuf_printf+0x21c> |
{ |
/* move format string chars to buffer until a */ |
/* format control is found. */ |
if (*ctrl != '%') |
{ |
vbuf_putchar(buf, *ctrl); |
1000160c: 19 c0 10 00 l.movhi r14,0x1000 |
} |
|
/* initialize all the flags for this format. */ |
dot_flag = long_flag = par.left_flag = par.do_padding = 0; |
par.pad_character = ' '; |
par.num2=32767; |
10001610: 9f 40 7f ff l.addi r26,r0,32767 |
{ |
/* move format string chars to buffer until a */ |
/* format control is found. */ |
if (*ctrl != '%') |
{ |
vbuf_putchar(buf, *ctrl); |
10001614: a9 ce 2f f4 l.ori r14,r14,0x2ff4 |
|
/* initialize all the flags for this format. */ |
dot_flag = long_flag = par.left_flag = par.do_padding = 0; |
par.pad_character = ' '; |
par.num2=32767; |
par.max_len = 10; |
10001618: 9f 00 00 0a l.addi r24,r0,10 |
1000161c: 00 00 00 08 l.j 1000163c <vbuf_printf+0x74> |
{ |
/* move format string chars to buffer until a */ |
/* format control is found. */ |
if (*ctrl != '%') |
{ |
vbuf_putchar(buf, *ctrl); |
10001620: 85 6e 00 00 l.lwz r11,0(r14) |
continue; |
10001624: ab 9e 00 00 l.ori r28,r30,0x0 |
{ |
/* move format string chars to buffer until a */ |
/* format control is found. */ |
if (*ctrl != '%') |
{ |
vbuf_putchar(buf, *ctrl); |
10001628: 48 00 58 00 l.jalr r11 |
params_t par; |
|
char ch; |
char* ctrl = (char*)ctrl1; |
|
for ( ; *ctrl; ctrl++) |
1000162c: 90 7c 00 01 l.lbs r3,1(r28) |
10001630: bc 03 00 00 l.sfeqi r3,0 |
10001634: 9f dc 00 01 l.addi r30,r28,1 |
10001638: 10 00 00 6b l.bf 100017e4 <vbuf_printf+0x21c> |
{ |
/* move format string chars to buffer until a */ |
/* format control is found. */ |
if (*ctrl != '%') |
1000163c: bc 03 00 25 l.sfeqi r3,37 |
10001640: 0f ff ff f8 l.bnf 10001620 <vbuf_printf+0x58> |
|
/* initialize all the flags for this format. */ |
dot_flag = long_flag = par.left_flag = par.do_padding = 0; |
par.pad_character = ' '; |
par.num2=32767; |
par.max_len = 10; |
10001644: 90 be 00 01 l.lbs r5,1(r30) |
continue; |
} |
|
/* initialize all the flags for this format. */ |
dot_flag = long_flag = par.left_flag = par.do_padding = 0; |
par.pad_character = ' '; |
10001648: 9c 60 00 20 l.addi r3,r0,32 |
vbuf_putchar(buf, *ctrl); |
continue; |
} |
|
/* initialize all the flags for this format. */ |
dot_flag = long_flag = par.left_flag = par.do_padding = 0; |
1000164c: 9c 40 00 00 l.addi r2,r0,0 |
par.pad_character = ' '; |
10001650: d8 01 18 0c l.sb 12(r1),r3 |
par.max_len = 10; |
|
try_next: |
ch = *(++ctrl); |
|
if ((ch >= '0' && ch <= '9')) |
10001654: a4 65 00 ff l.andi r3,r5,0xff |
vbuf_putchar(buf, *ctrl); |
continue; |
} |
|
/* initialize all the flags for this format. */ |
dot_flag = long_flag = par.left_flag = par.do_padding = 0; |
10001658: d4 01 10 10 l.sw 16(r1),r2 |
par.max_len = 10; |
|
try_next: |
ch = *(++ctrl); |
|
if ((ch >= '0' && ch <= '9')) |
1000165c: 9c 83 ff d0 l.addi r4,r3,-48 |
vbuf_putchar(buf, *ctrl); |
continue; |
} |
|
/* initialize all the flags for this format. */ |
dot_flag = long_flag = par.left_flag = par.do_padding = 0; |
10001660: d4 01 10 14 l.sw 20(r1),r2 |
par.max_len = 10; |
|
try_next: |
ch = *(++ctrl); |
|
if ((ch >= '0' && ch <= '9')) |
10001664: a4 84 00 ff l.andi r4,r4,0xff |
} |
|
/* initialize all the flags for this format. */ |
dot_flag = long_flag = par.left_flag = par.do_padding = 0; |
par.pad_character = ' '; |
par.num2=32767; |
10001668: d4 01 d0 08 l.sw 8(r1),r26 |
par.max_len = 10; |
1000166c: d4 01 c0 1c l.sw 28(r1),r24 |
|
try_next: |
ch = *(++ctrl); |
|
if ((ch >= '0' && ch <= '9')) |
10001670: bc 44 00 09 l.sfgtui r4,9 |
10001674: 9f 9e 00 01 l.addi r28,r30,1 |
} |
ctrl--; |
goto try_next; |
} |
|
par.uppercase = (ch >= 'A' && ch <= 'Z') ? 1 : 0; |
10001678: 9e 80 00 01 l.addi r20,r0,1 |
par.max_len = 10; |
|
try_next: |
ch = *(++ctrl); |
|
if ((ch >= '0' && ch <= '9')) |
1000167c: 10 00 00 1a l.bf 100016e4 <vbuf_printf+0x11c> |
{ |
if (dot_flag) |
10001680: bc 02 00 00 l.sfeqi r2,0 |
10001684: 10 00 00 9a l.bf 100018ec <vbuf_printf+0x324> |
10001688: 9c c0 00 00 l.addi r6,r0,0 |
1000168c: 9c 85 ff d0 l.addi r4,r5,-48 |
10001690: 00 00 00 02 l.j 10001698 <vbuf_printf+0xd0> |
char* cp; |
|
n = 0; |
cp = *linep; |
while (((*cp) >= '0' && (*cp) <= '9')) |
n = n*10 + ((*cp++) - '0'); |
10001694: ab 83 00 00 l.ori r28,r3,0x0 |
10001698: b8 e6 00 03 l.slli r7,r6,0x3 |
1000169c: 9c 7c 00 01 l.addi r3,r28,1 |
100016a0: e0 c6 30 00 l.add r6,r6,r6 |
long n; |
char* cp; |
|
n = 0; |
cp = *linep; |
while (((*cp) >= '0' && (*cp) <= '9')) |
100016a4: 90 a3 00 00 l.lbs r5,0(r3) |
n = n*10 + ((*cp++) - '0'); |
100016a8: e0 c6 38 00 l.add r6,r6,r7 |
100016ac: e0 c6 20 00 l.add r6,r6,r4 |
long n; |
char* cp; |
|
n = 0; |
cp = *linep; |
while (((*cp) >= '0' && (*cp) <= '9')) |
100016b0: 9c 85 ff d0 l.addi r4,r5,-48 |
100016b4: a4 e4 00 ff l.andi r7,r4,0xff |
100016b8: bc 47 00 09 l.sfgtui r7,9 |
100016bc: 0f ff ff f6 l.bnf 10001694 <vbuf_printf+0xcc> |
100016c0: a8 83 00 00 l.ori r4,r3,0x0 |
ch = *(++ctrl); |
|
if ((ch >= '0' && ch <= '9')) |
{ |
if (dot_flag) |
par.num2 = getnum(&ctrl); |
100016c4: d4 01 30 08 l.sw 8(r1),r6 |
par.pad_character = '0'; |
|
par.num1 = getnum(&ctrl); |
par.do_padding = 1; |
} |
ctrl--; |
100016c8: 9f c3 ff ff l.addi r30,r3,-1 |
100016cc: ab 84 00 00 l.ori r28,r4,0x0 |
par.max_len = 10; |
|
try_next: |
ch = *(++ctrl); |
|
if ((ch >= '0' && ch <= '9')) |
100016d0: a4 65 00 ff l.andi r3,r5,0xff |
100016d4: 9c 83 ff d0 l.addi r4,r3,-48 |
100016d8: a4 84 00 ff l.andi r4,r4,0xff |
100016dc: bc 44 00 09 l.sfgtui r4,9 |
100016e0: 0f ff ff e8 l.bnf 10001680 <vbuf_printf+0xb8> |
} |
ctrl--; |
goto try_next; |
} |
|
par.uppercase = (ch >= 'A' && ch <= 'Z') ? 1 : 0; |
100016e4: 9c 63 ff bf l.addi r3,r3,-65 |
100016e8: 9c 80 00 01 l.addi r4,r0,1 |
100016ec: a4 63 00 ff l.andi r3,r3,0xff |
100016f0: bc a3 00 19 l.sfleui r3,25 |
100016f4: 10 00 00 02 l.bf 100016fc <vbuf_printf+0x134> |
100016f8: 9c 80 00 00 l.addi r4,r0,0 |
100016fc: d4 01 20 18 l.sw 24(r1),r4 |
|
switch ((par.uppercase ? ch + 32: ch)) |
10001700: bc 04 00 00 l.sfeqi r4,0 |
10001704: a8 65 00 00 l.ori r3,r5,0x0 |
10001708: 10 00 00 02 l.bf 10001710 <vbuf_printf+0x148> |
1000170c: 9c 65 00 20 l.addi r3,r5,32 |
10001710: 9c 63 ff db l.addi r3,r3,-37 |
10001714: bc 43 00 53 l.sfgtui r3,83 |
10001718: 13 ff ff c5 l.bf 1000162c <vbuf_printf+0x64> |
1000171c: 18 80 10 00 l.movhi r4,0x1000 |
10001720: b8 63 00 02 l.slli r3,r3,0x2 |
10001724: a8 84 2b 24 l.ori r4,r4,0x2b24 |
10001728: e0 63 20 00 l.add r3,r3,r4 |
1000172c: 84 63 00 00 l.lwz r3,0(r3) |
10001730: 44 00 18 00 l.jr r3 |
} |
continue; |
#endif |
#ifdef PRINTF_STR_PRINT |
case 's': |
outs(buf, va_arg( argp, char*), &par); |
10001734: 86 d2 00 00 l.lwz r22,0(r18) |
10001738: 9e 52 00 04 l.addi r18,r18,4 |
//---------------------------------------------------- |
static int strlen(const char * str) |
{ |
const char * s; |
|
if(!str) |
1000173c: bc 16 00 00 l.sfeqi r22,0 |
10001740: 10 00 00 a4 l.bf 100019d0 <vbuf_printf+0x408> |
return 0; |
|
for(s = str; *s; ++ s) |
10001744: 90 56 00 00 l.lbs r2,0(r22) |
10001748: bc 02 00 00 l.sfeqi r2,0 |
1000174c: 10 00 00 07 l.bf 10001768 <vbuf_printf+0x1a0> |
10001750: a8 56 00 00 l.ori r2,r22,0x0 |
10001754: 9c 42 00 01 l.addi r2,r2,1 |
10001758: 90 62 00 00 l.lbs r3,0(r2) |
1000175c: bc 03 00 00 l.sfeqi r3,0 |
10001760: 0f ff ff fd l.bnf 10001754 <vbuf_printf+0x18c> |
10001764: e0 42 b0 02 l.sub r2,r2,r22 |
//---------------------------------------------------- |
#ifdef PRINTF_STR_PRINT |
static void outs( struct vbuf *buf, char* lp, params_t *par) |
{ |
/* pad on left if needed */ |
par->len = strlen( lp); |
10001768: d4 01 10 00 l.sw 0(r1),r2 |
#ifdef PRINTF_ENABLE_PADDING |
padding(buf, !(par->left_flag), par); |
#endif |
|
/* Move string to the buffer */ |
while (*lp && (par->num2)--) |
1000176c: 90 56 00 00 l.lbs r2,0(r22) |
10001770: bc 02 00 00 l.sfeqi r2,0 |
10001774: 10 00 00 16 l.bf 100017cc <vbuf_printf+0x204> |
10001778: 84 41 00 08 l.lwz r2,8(r1) |
1000177c: aa 96 00 00 l.ori r20,r22,0x0 |
10001780: 9c 62 ff ff l.addi r3,r2,-1 |
10001784: bc 22 00 00 l.sfnei r2,0 |
10001788: d4 01 18 08 l.sw 8(r1),r3 |
1000178c: 10 00 00 09 l.bf 100017b0 <vbuf_printf+0x1e8> |
10001790: 00 00 00 92 l.j 100019d8 <vbuf_printf+0x410> |
10001794: 84 61 00 08 l.lwz r3,8(r1) |
10001798: 9e 94 00 01 l.addi r20,r20,1 |
1000179c: 9c 83 ff ff l.addi r4,r3,-1 |
100017a0: bc 03 00 00 l.sfeqi r3,0 |
100017a4: d4 01 20 08 l.sw 8(r1),r4 |
100017a8: 10 00 00 72 l.bf 10001970 <vbuf_printf+0x3a8> |
vbuf_putchar(buf, *lp++); |
100017ac: aa c2 00 00 l.ori r22,r2,0x0 |
100017b0: 90 74 00 00 l.lbs r3,0(r20) |
100017b4: 85 6e 00 00 l.lwz r11,0(r14) |
100017b8: 9c 56 00 01 l.addi r2,r22,1 |
100017bc: 48 00 58 00 l.jalr r11 |
#ifdef PRINTF_ENABLE_PADDING |
padding(buf, !(par->left_flag), par); |
#endif |
|
/* Move string to the buffer */ |
while (*lp && (par->num2)--) |
100017c0: 90 62 00 00 l.lbs r3,0(r2) |
100017c4: bc 03 00 00 l.sfeqi r3,0 |
100017c8: 0f ff ff f3 l.bnf 10001794 <vbuf_printf+0x1cc> |
const char * s; |
|
if(!str) |
return 0; |
|
for(s = str; *s; ++ s) |
100017cc: 9c 60 00 00 l.addi r3,r0,0 |
/* Move string to the buffer */ |
while (*lp && (par->num2)--) |
vbuf_putchar(buf, *lp++); |
|
/* Pad on right if needed */ |
par->len = strlen( lp); |
100017d0: d4 01 18 00 l.sw 0(r1),r3 |
params_t par; |
|
char ch; |
char* ctrl = (char*)ctrl1; |
|
for ( ; *ctrl; ctrl++) |
100017d4: 90 7c 00 01 l.lbs r3,1(r28) |
100017d8: bc 03 00 00 l.sfeqi r3,0 |
100017dc: 9f dc 00 01 l.addi r30,r28,1 |
100017e0: 0f ff ff 97 l.bnf 1000163c <vbuf_printf+0x74> |
} |
goto try_next; |
} |
|
return res; |
} |
100017e4: 9c 21 00 4c l.addi r1,r1,76 |
100017e8: 9d 60 00 00 l.addi r11,r0,0 |
100017ec: 85 21 ff fc l.lwz r9,-4(r1) |
100017f0: 84 21 ff d4 l.lwz r1,-44(r1) |
100017f4: 84 41 ff d8 l.lwz r2,-40(r1) |
100017f8: 85 c1 ff dc l.lwz r14,-36(r1) |
100017fc: 86 41 ff e0 l.lwz r18,-32(r1) |
10001800: 86 81 ff e4 l.lwz r20,-28(r1) |
10001804: 86 c1 ff e8 l.lwz r22,-24(r1) |
10001808: 87 01 ff ec l.lwz r24,-20(r1) |
1000180c: 87 41 ff f0 l.lwz r26,-16(r1) |
10001810: 87 81 ff f4 l.lwz r28,-12(r1) |
10001814: 87 c1 ff f8 l.lwz r30,-8(r1) |
10001818: 44 00 48 00 l.jr r9 |
case 'x': |
case 'p': |
if (long_flag || ch == 'D') |
{ |
par.max_len = sizeof(long) * 2; |
outnum(buf, (long)va_arg(argp, long), 16L, &par); |
1000181c: 84 72 00 00 l.lwz r3,0(r18) |
#ifdef PRINTF_HEX_PRINT |
case 'x': |
case 'p': |
if (long_flag || ch == 'D') |
{ |
par.max_len = sizeof(long) * 2; |
10001820: 9c 40 00 08 l.addi r2,r0,8 |
outnum(buf, (long)va_arg(argp, long), 16L, &par); |
10001824: 9c 80 00 10 l.addi r4,r0,16 |
10001828: a8 a1 00 00 l.ori r5,r1,0x0 |
1000182c: 9e 52 00 04 l.addi r18,r18,4 |
#ifdef PRINTF_HEX_PRINT |
case 'x': |
case 'p': |
if (long_flag || ch == 'D') |
{ |
par.max_len = sizeof(long) * 2; |
10001830: d4 01 10 1c l.sw 28(r1),r2 |
outnum(buf, (long)va_arg(argp, long), 16L, &par); |
10001834: 07 ff fe b1 l.jal 100012f8 <outnum.isra.1> |
10001838: 03 ff ff 7d l.j 1000162c <vbuf_printf+0x64> |
1000183c: 9c 9e 00 02 l.addi r4,r30,2 |
10001840: 90 be 00 02 l.lbs r5,2(r30) |
par.pad_character = ' '; |
par.num2=32767; |
par.max_len = 10; |
|
try_next: |
ch = *(++ctrl); |
10001844: ab dc 00 00 l.ori r30,r28,0x0 |
10001848: ab 84 00 00 l.ori r28,r4,0x0 |
1000184c: 03 ff ff a1 l.j 100016d0 <vbuf_printf+0x108> |
{ |
outnum(buf, va_arg(argp, long), 10L, &par); |
continue; |
} |
else { |
outnum(buf, va_arg(argp, int), 10L, &par); |
10001850: 84 72 00 00 l.lwz r3,0(r18) |
10001854: 9c 80 00 0a l.addi r4,r0,10 |
10001858: a8 a1 00 00 l.ori r5,r1,0x0 |
1000185c: 9e 52 00 04 l.addi r18,r18,4 |
case 'x': |
case 'p': |
if (long_flag || ch == 'D') |
{ |
par.max_len = sizeof(long) * 2; |
outnum(buf, (long)va_arg(argp, long), 16L, &par); |
10001860: 07 ff fe a6 l.jal 100012f8 <outnum.isra.1> |
10001864: 03 ff ff 72 l.j 1000162c <vbuf_printf+0x64> |
outs(buf, va_arg( argp, char*), &par); |
continue; |
#endif |
#ifdef PRINTF_CHR_PRINT |
case 'c': |
vbuf_putchar(buf, va_arg( argp, int)); |
10001868: 90 72 00 03 l.lbs r3,3(r18) |
1000186c: 85 6e 00 00 l.lwz r11,0(r14) |
10001870: 9e 52 00 04 l.addi r18,r18,4 |
10001874: 48 00 58 00 l.jalr r11 |
continue; |
10001878: 03 ff ff 6d l.j 1000162c <vbuf_printf+0x64> |
#endif |
case '\\': |
switch (*ctrl) { |
1000187c: bc 05 00 68 l.sfeqi r5,104 |
10001880: 10 00 00 50 l.bf 100019c0 <vbuf_printf+0x3f8> |
10001884: bd 45 00 68 l.sfgtsi r5,104 |
10001888: 0c 00 00 30 l.bnf 10001948 <vbuf_printf+0x380> |
1000188c: bc 05 00 6e l.sfeqi r5,110 |
10001890: 10 00 00 48 l.bf 100019b0 <vbuf_printf+0x3e8> |
10001894: bc 05 00 72 l.sfeqi r5,114 |
10001898: 0c 00 00 42 l.bnf 100019a0 <vbuf_printf+0x3d8> |
break; |
case 'h': |
vbuf_putchar(buf, 0x08); |
break; |
case 'r': |
vbuf_putchar(buf, 0x0D); |
1000189c: 85 6e 00 00 l.lwz r11,0(r14) |
100018a0: 9c 60 00 0d l.addi r3,r0,13 |
100018a4: 48 00 58 00 l.jalr r11 |
break; |
100018a8: 00 00 00 2d l.j 1000195c <vbuf_printf+0x394> |
100018ac: 9c 9e 00 02 l.addi r4,r30,2 |
100018b0: 90 be 00 02 l.lbs r5,2(r30) |
case '-': |
par.left_flag = 1; |
break; |
|
case '.': |
dot_flag = 1; |
100018b4: 9c 40 00 01 l.addi r2,r0,1 |
par.pad_character = ' '; |
par.num2=32767; |
par.max_len = 10; |
|
try_next: |
ch = *(++ctrl); |
100018b8: ab dc 00 00 l.ori r30,r28,0x0 |
100018bc: ab 84 00 00 l.ori r28,r4,0x0 |
100018c0: 03 ff ff 84 l.j 100016d0 <vbuf_printf+0x108> |
100018c4: 9c 9e 00 02 l.addi r4,r30,2 |
100018c8: 90 be 00 02 l.lbs r5,2(r30) |
case '%': |
vbuf_putchar(buf, '%'); |
continue; |
|
case '-': |
par.left_flag = 1; |
100018cc: d4 01 a0 14 l.sw 20(r1),r20 |
par.pad_character = ' '; |
par.num2=32767; |
par.max_len = 10; |
|
try_next: |
ch = *(++ctrl); |
100018d0: ab dc 00 00 l.ori r30,r28,0x0 |
100018d4: ab 84 00 00 l.ori r28,r4,0x0 |
100018d8: 03 ff ff 7e l.j 100016d0 <vbuf_printf+0x108> |
par.uppercase = (ch >= 'A' && ch <= 'Z') ? 1 : 0; |
|
switch ((par.uppercase ? ch + 32: ch)) |
{ |
case '%': |
vbuf_putchar(buf, '%'); |
100018dc: 85 6e 00 00 l.lwz r11,0(r14) |
100018e0: 9c 60 00 25 l.addi r3,r0,37 |
100018e4: 48 00 58 00 l.jalr r11 |
continue; |
100018e8: 03 ff ff 51 l.j 1000162c <vbuf_printf+0x64> |
if ((ch >= '0' && ch <= '9')) |
{ |
if (dot_flag) |
par.num2 = getnum(&ctrl); |
else { |
if (ch == '0') |
100018ec: bc 25 00 30 l.sfnei r5,48 |
100018f0: 0c 00 00 14 l.bnf 10001940 <vbuf_printf+0x378> |
static long getnum( char** linep) |
{ |
long n; |
char* cp; |
|
n = 0; |
100018f4: 9c c0 00 00 l.addi r6,r0,0 |
100018f8: 9c 85 ff d0 l.addi r4,r5,-48 |
100018fc: 00 00 00 02 l.j 10001904 <vbuf_printf+0x33c> |
cp = *linep; |
while (((*cp) >= '0' && (*cp) <= '9')) |
n = n*10 + ((*cp++) - '0'); |
10001900: ab 83 00 00 l.ori r28,r3,0x0 |
10001904: b8 e6 00 03 l.slli r7,r6,0x3 |
10001908: 9c 7c 00 01 l.addi r3,r28,1 |
1000190c: e0 c6 30 00 l.add r6,r6,r6 |
long n; |
char* cp; |
|
n = 0; |
cp = *linep; |
while (((*cp) >= '0' && (*cp) <= '9')) |
10001910: 90 a3 00 00 l.lbs r5,0(r3) |
n = n*10 + ((*cp++) - '0'); |
10001914: e0 c6 38 00 l.add r6,r6,r7 |
10001918: e0 c6 20 00 l.add r6,r6,r4 |
long n; |
char* cp; |
|
n = 0; |
cp = *linep; |
while (((*cp) >= '0' && (*cp) <= '9')) |
1000191c: 9c 85 ff d0 l.addi r4,r5,-48 |
10001920: a4 e4 00 ff l.andi r7,r4,0xff |
10001924: bc 47 00 09 l.sfgtui r7,9 |
10001928: 0f ff ff f6 l.bnf 10001900 <vbuf_printf+0x338> |
1000192c: a8 83 00 00 l.ori r4,r3,0x0 |
par.num2 = getnum(&ctrl); |
else { |
if (ch == '0') |
par.pad_character = '0'; |
|
par.num1 = getnum(&ctrl); |
10001930: d4 01 30 04 l.sw 4(r1),r6 |
par.do_padding = 1; |
10001934: d4 01 a0 10 l.sw 16(r1),r20 |
} |
ctrl--; |
10001938: 9f c3 ff ff l.addi r30,r3,-1 |
1000193c: 03 ff ff 64 l.j 100016cc <vbuf_printf+0x104> |
{ |
if (dot_flag) |
par.num2 = getnum(&ctrl); |
else { |
if (ch == '0') |
par.pad_character = '0'; |
10001940: d8 01 28 0c l.sb 12(r1),r5 |
10001944: 03 ff ff ec l.j 100018f4 <vbuf_printf+0x32c> |
case 'c': |
vbuf_putchar(buf, va_arg( argp, int)); |
continue; |
#endif |
case '\\': |
switch (*ctrl) { |
10001948: bc 05 00 61 l.sfeqi r5,97 |
1000194c: 0c 00 00 15 l.bnf 100019a0 <vbuf_printf+0x3d8> |
case 'a': |
vbuf_putchar(buf, 0x07); |
10001950: 85 6e 00 00 l.lwz r11,0(r14) |
10001954: 9c 60 00 07 l.addi r3,r0,7 |
10001958: 48 00 58 00 l.jalr r11 |
1000195c: 9c 9e 00 03 l.addi r4,r30,3 |
10001960: 90 be 00 03 l.lbs r5,3(r30) |
10001964: ab 84 00 00 l.ori r28,r4,0x0 |
break; |
default: |
vbuf_putchar(buf, *ctrl); |
break; |
} |
ctrl++; |
10001968: 9f de 00 02 l.addi r30,r30,2 |
1000196c: 03 ff ff 59 l.j 100016d0 <vbuf_printf+0x108> |
10001970: 90 76 00 01 l.lbs r3,1(r22) |
const char * s; |
|
if(!str) |
return 0; |
|
for(s = str; *s; ++ s) |
10001974: bc 03 00 00 l.sfeqi r3,0 |
10001978: 9c 60 00 00 l.addi r3,r0,0 |
1000197c: 13 ff ff 95 l.bf 100017d0 <vbuf_printf+0x208> |
10001980: a8 62 00 00 l.ori r3,r2,0x0 |
10001984: 9c 63 00 01 l.addi r3,r3,1 |
10001988: 90 83 00 00 l.lbs r4,0(r3) |
1000198c: bc 04 00 00 l.sfeqi r4,0 |
10001990: 0f ff ff fd l.bnf 10001984 <vbuf_printf+0x3bc> |
10001994: e0 63 10 02 l.sub r3,r3,r2 |
/* Move string to the buffer */ |
while (*lp && (par->num2)--) |
vbuf_putchar(buf, *lp++); |
|
/* Pad on right if needed */ |
par->len = strlen( lp); |
10001998: d4 01 18 00 l.sw 0(r1),r3 |
1000199c: 03 ff ff 8e l.j 100017d4 <vbuf_printf+0x20c> |
break; |
case 'n': |
vbuf_putchar(buf, 0x0A); |
break; |
default: |
vbuf_putchar(buf, *ctrl); |
100019a0: 90 7e 00 01 l.lbs r3,1(r30) |
100019a4: 85 6e 00 00 l.lwz r11,0(r14) |
100019a8: 48 00 58 00 l.jalr r11 |
break; |
100019ac: 03 ff ff ec l.j 1000195c <vbuf_printf+0x394> |
break; |
case 'r': |
vbuf_putchar(buf, 0x0D); |
break; |
case 'n': |
vbuf_putchar(buf, 0x0A); |
100019b0: 85 6e 00 00 l.lwz r11,0(r14) |
100019b4: 9c 60 00 0a l.addi r3,r0,10 |
100019b8: 48 00 58 00 l.jalr r11 |
break; |
100019bc: 03 ff ff e8 l.j 1000195c <vbuf_printf+0x394> |
switch (*ctrl) { |
case 'a': |
vbuf_putchar(buf, 0x07); |
break; |
case 'h': |
vbuf_putchar(buf, 0x08); |
100019c0: 85 6e 00 00 l.lwz r11,0(r14) |
100019c4: 9c 60 00 08 l.addi r3,r0,8 |
100019c8: 48 00 58 00 l.jalr r11 |
break; |
100019cc: 03 ff ff e4 l.j 1000195c <vbuf_printf+0x394> |
static int strlen(const char * str) |
{ |
const char * s; |
|
if(!str) |
return 0; |
100019d0: a8 56 00 00 l.ori r2,r22,0x0 |
100019d4: 03 ff ff 65 l.j 10001768 <vbuf_printf+0x1a0> |
100019d8: 90 76 00 00 l.lbs r3,0(r22) |
#ifdef PRINTF_ENABLE_PADDING |
padding(buf, !(par->left_flag), par); |
#endif |
|
/* Move string to the buffer */ |
while (*lp && (par->num2)--) |
100019dc: a8 56 00 00 l.ori r2,r22,0x0 |
100019e0: 03 ff ff e5 l.j 10001974 <vbuf_printf+0x3ac> |
|
100019e4 <printf>: |
{ |
int res = 0; |
va_list argp; |
struct vbuf buf; |
|
if (_stdout && ctrl1) |
100019e4: 18 a0 10 00 l.movhi r5,0x1000 |
} |
//---------------------------------------------------- |
// printf: Console based printf |
//---------------------------------------------------- |
int printf( const char* ctrl1, ... ) |
{ |
100019e8: d7 e1 4f fc l.sw -4(r1),r9 |
int res = 0; |
va_list argp; |
struct vbuf buf; |
|
if (_stdout && ctrl1) |
100019ec: a8 a5 2f f4 l.ori r5,r5,0x2ff4 |
} |
//---------------------------------------------------- |
// printf: Console based printf |
//---------------------------------------------------- |
int printf( const char* ctrl1, ... ) |
{ |
100019f0: d7 e1 0f f4 l.sw -12(r1),r1 |
int res = 0; |
va_list argp; |
struct vbuf buf; |
|
if (_stdout && ctrl1) |
100019f4: 85 65 00 00 l.lwz r11,0(r5) |
} |
//---------------------------------------------------- |
// printf: Console based printf |
//---------------------------------------------------- |
int printf( const char* ctrl1, ... ) |
{ |
100019f8: d7 e1 17 f8 l.sw -8(r1),r2 |
int res = 0; |
va_list argp; |
struct vbuf buf; |
|
if (_stdout && ctrl1) |
100019fc: bc 0b 00 00 l.sfeqi r11,0 |
} |
//---------------------------------------------------- |
// printf: Console based printf |
//---------------------------------------------------- |
int printf( const char* ctrl1, ... ) |
{ |
10001a00: 9c 21 ff e4 l.addi r1,r1,-28 |
10001a04: a8 83 00 00 l.ori r4,r3,0x0 |
int res = 0; |
va_list argp; |
struct vbuf buf; |
|
if (_stdout && ctrl1) |
10001a08: 10 00 00 09 l.bf 10001a2c <printf+0x48> |
{ |
va_start( argp, ctrl1); |
|
// Setup target to be stdout function |
buf.function = _stdout; |
buf.buffer = 0; |
10001a0c: 9c 40 00 00 l.addi r2,r0,0 |
buf.offset = 0; |
buf.max_length = 0; |
|
res = vbuf_printf(&buf, ctrl1, argp); |
10001a10: a8 61 00 00 l.ori r3,r1,0x0 |
10001a14: 9c a1 00 1c l.addi r5,r1,28 |
if (_stdout && ctrl1) |
{ |
va_start( argp, ctrl1); |
|
// Setup target to be stdout function |
buf.function = _stdout; |
10001a18: d4 01 58 00 l.sw 0(r1),r11 |
buf.buffer = 0; |
10001a1c: d4 01 10 04 l.sw 4(r1),r2 |
buf.offset = 0; |
10001a20: d4 01 10 08 l.sw 8(r1),r2 |
buf.max_length = 0; |
10001a24: d4 01 10 0c l.sw 12(r1),r2 |
|
res = vbuf_printf(&buf, ctrl1, argp); |
10001a28: 07 ff fe e8 l.jal 100015c8 <vbuf_printf> |
|
va_end( argp); |
} |
|
return res; |
} |
10001a2c: 9c 21 00 1c l.addi r1,r1,28 |
10001a30: 85 21 ff fc l.lwz r9,-4(r1) |
10001a34: 84 21 ff f4 l.lwz r1,-12(r1) |
10001a38: 84 41 ff f8 l.lwz r2,-8(r1) |
10001a3c: 44 00 48 00 l.jr r9 |
|
10001a40 <serial_init>: |
|
//------------------------------------------------------------- |
// serial_init: |
//------------------------------------------------------------- |
void serial_init (void) |
{ |
10001a40: d7 e1 0f fc l.sw -4(r1),r1 |
10001a44: 9c 21 ff fc l.addi r1,r1,-4 |
|
} |
10001a48: 9c 21 00 04 l.addi r1,r1,4 |
10001a4c: 84 21 ff fc l.lwz r1,-4(r1) |
10001a50: 44 00 48 00 l.jr r9 |
|
10001a54 <serial_putchar>: |
//------------------------------------------------------------- |
// serial_putchar: Write character to Serial Port (used by printf) |
//------------------------------------------------------------- |
int serial_putchar(char ch) |
{ |
10001a54: b8 63 00 18 l.slli r3,r3,0x18 |
10001a58: d7 e1 17 f8 l.sw -8(r1),r2 |
10001a5c: d7 e1 4f fc l.sw -4(r1),r9 |
10001a60: b8 43 00 98 l.srai r2,r3,0x18 |
10001a64: d7 e1 0f f4 l.sw -12(r1),r1 |
10001a68: 9c 21 ff f4 l.addi r1,r1,-12 |
if (ch == '\n') |
10001a6c: bc 22 00 0a l.sfnei r2,10 |
10001a70: 0c 00 00 10 l.bnf 10001ab0 <serial_putchar+0x5c> |
serial_putchar('\r'); |
|
{ |
register char t1 asm ("r3") = ch; |
10001a74: a8 62 00 00 l.ori r3,r2,0x0 |
asm volatile ("\tl.nop\t%0" : : "K" (0x0004), "r" (t1)); |
10001a78: 15 00 00 04 l.nop 0x4 |
} |
|
UART_UDR = ch; |
10001a7c: 18 60 12 00 l.movhi r3,0x1200 |
10001a80: a8 83 00 08 l.ori r4,r3,0x8 |
while (UART_USR & UART_TX_BUSY); |
10001a84: a8 63 00 04 l.ori r3,r3,0x4 |
{ |
register char t1 asm ("r3") = ch; |
asm volatile ("\tl.nop\t%0" : : "K" (0x0004), "r" (t1)); |
} |
|
UART_UDR = ch; |
10001a88: d4 04 10 00 l.sw 0(r4),r2 |
while (UART_USR & UART_TX_BUSY); |
10001a8c: 85 63 00 00 l.lwz r11,0(r3) |
10001a90: a5 6b 00 08 l.andi r11,r11,0x8 |
10001a94: bc 0b 00 00 l.sfeqi r11,0 |
10001a98: 0f ff ff fd l.bnf 10001a8c <serial_putchar+0x38> |
|
return 0; |
} |
10001a9c: 9c 21 00 0c l.addi r1,r1,12 |
10001aa0: 85 21 ff fc l.lwz r9,-4(r1) |
10001aa4: 84 21 ff f4 l.lwz r1,-12(r1) |
10001aa8: 84 41 ff f8 l.lwz r2,-8(r1) |
10001aac: 44 00 48 00 l.jr r9 |
// serial_putchar: Write character to Serial Port (used by printf) |
//------------------------------------------------------------- |
int serial_putchar(char ch) |
{ |
if (ch == '\n') |
serial_putchar('\r'); |
10001ab0: 9c 60 00 0d l.addi r3,r0,13 |
10001ab4: 07 ff ff e8 l.jal 10001a54 <serial_putchar> |
10001ab8: 03 ff ff ef l.j 10001a74 <serial_putchar+0x20> |
|
10001abc <serial_getchar>: |
// serial_haschar: |
//------------------------------------------------------------- |
int serial_haschar() |
{ |
#ifndef USE_NOP_PUTC |
return (UART_USR & UART_RX_AVAIL); |
10001abc: 18 60 12 00 l.movhi r3,0x1200 |
} |
//------------------------------------------------------------- |
// serial_getchar: Read character from Serial Port |
//------------------------------------------------------------- |
int serial_getchar (void) |
{ |
10001ac0: d7 e1 0f fc l.sw -4(r1),r1 |
// serial_haschar: |
//------------------------------------------------------------- |
int serial_haschar() |
{ |
#ifndef USE_NOP_PUTC |
return (UART_USR & UART_RX_AVAIL); |
10001ac4: a8 83 00 04 l.ori r4,r3,0x4 |
} |
//------------------------------------------------------------- |
// serial_getchar: Read character from Serial Port |
//------------------------------------------------------------- |
int serial_getchar (void) |
{ |
10001ac8: 9c 21 ff fc l.addi r1,r1,-4 |
// serial_haschar: |
//------------------------------------------------------------- |
int serial_haschar() |
{ |
#ifndef USE_NOP_PUTC |
return (UART_USR & UART_RX_AVAIL); |
10001acc: 84 84 00 00 l.lwz r4,0(r4) |
10001ad0: a4 84 00 01 l.andi r4,r4,0x1 |
//------------------------------------------------------------- |
int serial_getchar (void) |
{ |
// Read character in from UART0 Recieve Buffer and return |
#ifndef USE_NOP_PUTC |
if (serial_haschar()) |
10001ad4: bc 04 00 00 l.sfeqi r4,0 |
10001ad8: 10 00 00 06 l.bf 10001af0 <serial_getchar+0x34> |
return UART_UDR; |
10001adc: a8 63 00 08 l.ori r3,r3,0x8 |
10001ae0: 85 63 00 00 l.lwz r11,0(r3) |
else |
#endif |
return -1; |
} |
10001ae4: 9c 21 00 04 l.addi r1,r1,4 |
10001ae8: 84 21 ff fc l.lwz r1,-4(r1) |
10001aec: 44 00 48 00 l.jr r9 |
#ifndef USE_NOP_PUTC |
if (serial_haschar()) |
return UART_UDR; |
else |
#endif |
return -1; |
10001af0: 9d 60 ff ff l.addi r11,r0,-1 |
10001af4: 03 ff ff fc l.j 10001ae4 <serial_getchar+0x28> |
|
10001af8 <serial_haschar>: |
// serial_haschar: |
//------------------------------------------------------------- |
int serial_haschar() |
{ |
#ifndef USE_NOP_PUTC |
return (UART_USR & UART_RX_AVAIL); |
10001af8: 18 60 12 00 l.movhi r3,0x1200 |
} |
//------------------------------------------------------------- |
// serial_haschar: |
//------------------------------------------------------------- |
int serial_haschar() |
{ |
10001afc: d7 e1 0f fc l.sw -4(r1),r1 |
#ifndef USE_NOP_PUTC |
return (UART_USR & UART_RX_AVAIL); |
10001b00: a8 63 00 04 l.ori r3,r3,0x4 |
} |
//------------------------------------------------------------- |
// serial_haschar: |
//------------------------------------------------------------- |
int serial_haschar() |
{ |
10001b04: 9c 21 ff fc l.addi r1,r1,-4 |
#ifndef USE_NOP_PUTC |
return (UART_USR & UART_RX_AVAIL); |
10001b08: 85 63 00 00 l.lwz r11,0(r3) |
#else |
return 0; |
#endif |
} |
10001b0c: 9c 21 00 04 l.addi r1,r1,4 |
10001b10: a5 6b 00 01 l.andi r11,r11,0x1 |
10001b14: 84 21 ff fc l.lwz r1,-4(r1) |
10001b18: 44 00 48 00 l.jr r9 |
|
10001b1c <serial_putstr>: |
//------------------------------------------------------------- |
// serial_putstr: |
//------------------------------------------------------------- |
void serial_putstr(char *str) |
{ |
10001b1c: d7 e1 17 f8 l.sw -8(r1),r2 |
10001b20: d7 e1 4f fc l.sw -4(r1),r9 |
10001b24: d7 e1 0f f4 l.sw -12(r1),r1 |
10001b28: a8 43 00 00 l.ori r2,r3,0x0 |
while (*str) |
10001b2c: 90 63 00 00 l.lbs r3,0(r3) |
10001b30: bc 23 00 00 l.sfnei r3,0 |
} |
//------------------------------------------------------------- |
// serial_putstr: |
//------------------------------------------------------------- |
void serial_putstr(char *str) |
{ |
10001b34: 9c 21 ff f4 l.addi r1,r1,-12 |
while (*str) |
10001b38: 0c 00 00 06 l.bnf 10001b50 <serial_putstr+0x34> |
serial_putchar(*str++); |
10001b3c: 9c 42 00 01 l.addi r2,r2,1 |
10001b40: 07 ff ff c5 l.jal 10001a54 <serial_putchar> |
//------------------------------------------------------------- |
// serial_putstr: |
//------------------------------------------------------------- |
void serial_putstr(char *str) |
{ |
while (*str) |
10001b44: 90 62 00 00 l.lbs r3,0(r2) |
10001b48: bc 03 00 00 l.sfeqi r3,0 |
10001b4c: 0f ff ff fc l.bnf 10001b3c <serial_putstr+0x20> |
serial_putchar(*str++); |
} |
10001b50: 9c 21 00 0c l.addi r1,r1,12 |
10001b54: 85 21 ff fc l.lwz r9,-4(r1) |
10001b58: 84 21 ff f4 l.lwz r1,-12(r1) |
10001b5c: 84 41 ff f8 l.lwz r2,-8(r1) |
10001b60: 44 00 48 00 l.jr r9 |
|
10001b64 <serial_putnum>: |
//------------------------------------------------------------- |
// serial_putnum: |
//------------------------------------------------------------- |
void serial_putnum( int n ) |
{ |
10001b64: d7 e1 17 e8 l.sw -24(r1),r2 |
char* cp; |
int negative; |
char outbuf[32]; |
const char digits[] = "0123456789ABCDEF"; |
10001b68: 18 40 30 31 l.movhi r2,0x3031 |
} |
//------------------------------------------------------------- |
// serial_putnum: |
//------------------------------------------------------------- |
void serial_putnum( int n ) |
{ |
10001b6c: d7 e1 4f fc l.sw -4(r1),r9 |
char* cp; |
int negative; |
char outbuf[32]; |
const char digits[] = "0123456789ABCDEF"; |
10001b70: a8 42 32 33 l.ori r2,r2,0x3233 |
} |
//------------------------------------------------------------- |
// serial_putnum: |
//------------------------------------------------------------- |
void serial_putnum( int n ) |
{ |
10001b74: d7 e1 0f e4 l.sw -28(r1),r1 |
10001b78: d7 e1 77 ec l.sw -20(r1),r14 |
10001b7c: d7 e1 97 f0 l.sw -16(r1),r18 |
10001b80: d7 e1 a7 f4 l.sw -12(r1),r20 |
10001b84: d7 e1 b7 f8 l.sw -8(r1),r22 |
10001b88: 9c 21 ff b0 l.addi r1,r1,-80 |
char outbuf[32]; |
const char digits[] = "0123456789ABCDEF"; |
unsigned long num; |
|
/* Check if number is negative */ |
if (n < 0L) { |
10001b8c: bd 63 00 00 l.sfgesi r3,0 |
void serial_putnum( int n ) |
{ |
char* cp; |
int negative; |
char outbuf[32]; |
const char digits[] = "0123456789ABCDEF"; |
10001b90: d4 01 10 00 l.sw 0(r1),r2 |
10001b94: 18 40 34 35 l.movhi r2,0x3435 |
10001b98: a8 42 36 37 l.ori r2,r2,0x3637 |
10001b9c: d4 01 10 04 l.sw 4(r1),r2 |
10001ba0: 18 40 38 39 l.movhi r2,0x3839 |
10001ba4: a8 42 41 42 l.ori r2,r2,0x4142 |
10001ba8: d4 01 10 08 l.sw 8(r1),r2 |
10001bac: 18 40 43 44 l.movhi r2,0x4344 |
10001bb0: a8 42 45 46 l.ori r2,r2,0x4546 |
10001bb4: d4 01 10 0c l.sw 12(r1),r2 |
10001bb8: 9c 40 00 00 l.addi r2,r0,0 |
10001bbc: d8 01 10 10 l.sb 16(r1),r2 |
unsigned long num; |
|
/* Check if number is negative */ |
if (n < 0L) { |
10001bc0: 0c 00 00 2e l.bnf 10001c78 <serial_putnum+0x114> |
negative = 1; |
num = -(n); |
} |
else{ |
num = (n); |
10001bc4: a8 43 00 00 l.ori r2,r3,0x0 |
negative = 0; |
10001bc8: 9e c0 00 00 l.addi r22,r0,0 |
10001bcc: 9e 81 00 14 l.addi r20,r1,20 |
10001bd0: a9 d4 00 00 l.ori r14,r20,0x0 |
10001bd4: 00 00 00 02 l.j 10001bdc <serial_putnum+0x78> |
10001bd8: a9 d2 00 00 l.ori r14,r18,0x0 |
} |
|
/* Build number (backwards) in outbuf */ |
cp = outbuf; |
do { |
*cp++ = digits[(int)(num % 10)]; |
10001bdc: a8 62 00 00 l.ori r3,r2,0x0 |
10001be0: 9c 80 00 0a l.addi r4,r0,10 |
serial_putchar(*str++); |
} |
//------------------------------------------------------------- |
// serial_putnum: |
//------------------------------------------------------------- |
void serial_putnum( int n ) |
10001be4: 9e 4e 00 01 l.addi r18,r14,1 |
} |
|
/* Build number (backwards) in outbuf */ |
cp = outbuf; |
do { |
*cp++ = digits[(int)(num % 10)]; |
10001be8: 04 00 03 4e l.jal 10002920 <__umodsi3> |
10001bec: 9c 61 00 00 l.addi r3,r1,0 |
} while ((num /= 10) > 0); |
10001bf0: 9c 80 00 0a l.addi r4,r0,10 |
} |
|
/* Build number (backwards) in outbuf */ |
cp = outbuf; |
do { |
*cp++ = digits[(int)(num % 10)]; |
10001bf4: e1 63 58 00 l.add r11,r3,r11 |
} while ((num /= 10) > 0); |
10001bf8: a8 62 00 00 l.ori r3,r2,0x0 |
} |
|
/* Build number (backwards) in outbuf */ |
cp = outbuf; |
do { |
*cp++ = digits[(int)(num % 10)]; |
10001bfc: 8d 6b 00 00 l.lbz r11,0(r11) |
10001c00: d8 0e 58 00 l.sb 0(r14),r11 |
} while ((num /= 10) > 0); |
10001c04: 04 00 03 3e l.jal 100028fc <__udivsi3> |
10001c08: bc 0b 00 00 l.sfeqi r11,0 |
10001c0c: a8 4b 00 00 l.ori r2,r11,0x0 |
10001c10: 0f ff ff f2 l.bnf 10001bd8 <serial_putnum+0x74> |
if (negative) |
10001c14: bc 16 00 00 l.sfeqi r22,0 |
10001c18: 10 00 00 04 l.bf 10001c28 <serial_putnum+0xc4> |
*cp++ = '-'; |
10001c1c: 9c 40 00 2d l.addi r2,r0,45 |
10001c20: 9e 4e 00 02 l.addi r18,r14,2 |
10001c24: d8 0e 10 01 l.sb 1(r14),r2 |
*cp-- = 0; |
10001c28: 9c 52 ff ff l.addi r2,r18,-1 |
10001c2c: 9c 60 00 00 l.addi r3,r0,0 |
|
while (cp >= outbuf) |
10001c30: e4 62 a0 00 l.sfgeu r2,r20 |
do { |
*cp++ = digits[(int)(num % 10)]; |
} while ((num /= 10) > 0); |
if (negative) |
*cp++ = '-'; |
*cp-- = 0; |
10001c34: d8 12 18 00 l.sb 0(r18),r3 |
|
while (cp >= outbuf) |
10001c38: 0c 00 00 07 l.bnf 10001c54 <serial_putnum+0xf0> |
serial_putchar(*str++); |
} |
//------------------------------------------------------------- |
// serial_putnum: |
//------------------------------------------------------------- |
void serial_putnum( int n ) |
10001c3c: 9d d4 ff ff l.addi r14,r20,-1 |
if (negative) |
*cp++ = '-'; |
*cp-- = 0; |
|
while (cp >= outbuf) |
serial_putchar(*cp--); |
10001c40: 90 62 00 00 l.lbs r3,0(r2) |
10001c44: 9c 42 ff ff l.addi r2,r2,-1 |
10001c48: 07 ff ff 83 l.jal 10001a54 <serial_putchar> |
} while ((num /= 10) > 0); |
if (negative) |
*cp++ = '-'; |
*cp-- = 0; |
|
while (cp >= outbuf) |
10001c4c: e4 02 70 00 l.sfeq r2,r14 |
10001c50: 0f ff ff fc l.bnf 10001c40 <serial_putnum+0xdc> |
serial_putchar(*cp--); |
} |
10001c54: 9c 21 00 50 l.addi r1,r1,80 |
10001c58: 85 21 ff fc l.lwz r9,-4(r1) |
10001c5c: 84 21 ff e4 l.lwz r1,-28(r1) |
10001c60: 84 41 ff e8 l.lwz r2,-24(r1) |
10001c64: 85 c1 ff ec l.lwz r14,-20(r1) |
10001c68: 86 41 ff f0 l.lwz r18,-16(r1) |
10001c6c: 86 81 ff f4 l.lwz r20,-12(r1) |
10001c70: 86 c1 ff f8 l.lwz r22,-8(r1) |
10001c74: 44 00 48 00 l.jr r9 |
unsigned long num; |
|
/* Check if number is negative */ |
if (n < 0L) { |
negative = 1; |
num = -(n); |
10001c78: e0 40 18 02 l.sub r2,r0,r3 |
const char digits[] = "0123456789ABCDEF"; |
unsigned long num; |
|
/* Check if number is negative */ |
if (n < 0L) { |
negative = 1; |
10001c7c: 9e c0 00 01 l.addi r22,r0,1 |
10001c80: 03 ff ff d3 l.j 10001bcc <serial_putnum+0x68> |
|
10001c84 <timer_init>: |
|
//-------------------------------------------------------------------------- |
// timer_init: |
//-------------------------------------------------------------------------- |
void timer_init(void) |
{ |
10001c84: d7 e1 0f fc l.sw -4(r1),r1 |
10001c88: 9c 21 ff fc l.addi r1,r1,-4 |
|
} |
10001c8c: 9c 21 00 04 l.addi r1,r1,4 |
10001c90: 84 21 ff fc l.lwz r1,-4(r1) |
10001c94: 44 00 48 00 l.jr r9 |
|
10001c98 <timer_sleep>: |
// Prototypes: |
//----------------------------------------------------------------- |
|
// General timer |
void timer_init(void); |
static t_time timer_now(void) { return TIMER_VAL; } |
10001c98: 18 a0 12 00 l.movhi r5,0x1200 |
//-------------------------------------------------------------------------- |
// timer_sleep: |
//-------------------------------------------------------------------------- |
void timer_sleep(int timeMs) |
{ |
10001c9c: d7 e1 0f fc l.sw -4(r1),r1 |
10001ca0: a8 a5 01 00 l.ori r5,r5,0x100 |
10001ca4: 9c 21 ff fc l.addi r1,r1,-4 |
10001ca8: 84 c5 00 00 l.lwz r6,0(r5) |
10001cac: 84 85 00 00 l.lwz r4,0(r5) |
static long timer_diff(t_time a, t_time b) { return (long)(a - b); } |
10001cb0: e0 84 30 02 l.sub r4,r4,r6 |
t_time t = timer_now(); |
|
while (timer_diff(timer_now(), t) < timeMs) |
10001cb4: e5 a3 20 00 l.sfles r3,r4 |
10001cb8: 0f ff ff fd l.bnf 10001cac <timer_sleep+0x14> |
; |
} |
10001cbc: 9c 21 00 04 l.addi r1,r1,4 |
10001cc0: 84 21 ff fc l.lwz r1,-4(r1) |
10001cc4: 44 00 48 00 l.jr r9 |
|
10001cc8 <empty_syscall>: |
volatile int syscall_done = 0; |
|
//----------------------------------------------------------------- |
// Syscall handling: |
//----------------------------------------------------------------- |
void empty_syscall(void) { syscall_done = 1; } |
10001cc8: 18 60 10 00 l.movhi r3,0x1000 |
10001ccc: 9c 80 00 01 l.addi r4,r0,1 |
10001cd0: a8 63 2f f8 l.ori r3,r3,0x2ff8 |
10001cd4: d7 e1 0f fc l.sw -4(r1),r1 |
10001cd8: 9c 21 ff fc l.addi r1,r1,-4 |
10001cdc: d4 03 20 00 l.sw 0(r3),r4 |
10001ce0: 9c 21 00 04 l.addi r1,r1,4 |
10001ce4: 84 21 ff fc l.lwz r1,-4(r1) |
10001ce8: 44 00 48 00 l.jr r9 |
|
10001cec <test>: |
unsigned short sw; |
unsigned short *psw; |
unsigned char sb; |
unsigned char *psb; |
|
serial_putstr("\nTest:\n"); |
10001cec: 18 60 10 00 l.movhi r3,0x1000 |
|
//----------------------------------------------------------------- |
// main: |
//----------------------------------------------------------------- |
int test(void) |
{ |
10001cf0: d7 e1 4f fc l.sw -4(r1),r9 |
10001cf4: d7 e1 17 f0 l.sw -16(r1),r2 |
10001cf8: d7 e1 0f ec l.sw -20(r1),r1 |
10001cfc: d7 e1 77 f4 l.sw -12(r1),r14 |
10001d00: d7 e1 97 f8 l.sw -8(r1),r18 |
unsigned short sw; |
unsigned short *psw; |
unsigned char sb; |
unsigned char *psb; |
|
serial_putstr("\nTest:\n"); |
10001d04: a8 63 2d 09 l.ori r3,r3,0x2d09 |
|
//----------------------------------------------------------------- |
// main: |
//----------------------------------------------------------------- |
int test(void) |
{ |
10001d08: 9c 21 ff e0 l.addi r1,r1,-32 |
|
// Assign empty syscall handler |
exception_register_syscall_handler(empty_syscall); |
|
serial_putstr("1. Initialised data\n"); |
assert(var == 0x1234); // .text |
10001d0c: 18 40 10 00 l.movhi r2,0x1000 |
unsigned short sw; |
unsigned short *psw; |
unsigned char sb; |
unsigned char *psb; |
|
serial_putstr("\nTest:\n"); |
10001d10: 07 ff ff 83 l.jal 10001b1c <serial_putstr> |
|
// Adjust ISR vector to match this app's vector offset |
asm_set_isr_vector(asm_save_context); |
|
// Assign empty syscall handler |
exception_register_syscall_handler(empty_syscall); |
10001d14: 18 60 10 00 l.movhi r3,0x1000 |
|
serial_putstr("1. Initialised data\n"); |
assert(var == 0x1234); // .text |
10001d18: a8 42 2f d8 l.ori r2,r2,0x2fd8 |
|
// Adjust ISR vector to match this app's vector offset |
asm_set_isr_vector(asm_save_context); |
|
// Assign empty syscall handler |
exception_register_syscall_handler(empty_syscall); |
10001d1c: a8 63 1c c8 l.ori r3,r3,0x1cc8 |
10001d20: 07 ff fc e2 l.jal 100010a8 <exception_register_syscall_handler> |
|
serial_putstr("1. Initialised data\n"); |
10001d24: 18 60 10 00 l.movhi r3,0x1000 |
10001d28: a8 63 2d 11 l.ori r3,r3,0x2d11 |
10001d2c: 07 ff ff 7c l.jal 10001b1c <serial_putstr> |
assert(var == 0x1234); // .text |
10001d30: 84 62 00 00 l.lwz r3,0(r2) |
10001d34: bc 03 12 34 l.sfeqi r3,4660 |
10001d38: 10 00 00 0e l.bf 10001d70 <test+0x84> |
10001d3c: 18 60 10 00 l.movhi r3,0x1000 |
10001d40: a8 63 2d 26 l.ori r3,r3,0x2d26 |
10001d44: d4 01 18 00 l.sw 0(r1),r3 |
10001d48: 18 60 10 00 l.movhi r3,0x1000 |
10001d4c: a8 63 2d 34 l.ori r3,r3,0x2d34 |
10001d50: d4 01 18 04 l.sw 4(r1),r3 |
10001d54: 9c 60 00 29 l.addi r3,r0,41 |
10001d58: d4 01 18 08 l.sw 8(r1),r3 |
10001d5c: 18 60 10 00 l.movhi r3,0x1000 |
10001d60: a8 63 2c 74 l.ori r3,r3,0x2c74 |
10001d64: 07 ff ff 20 l.jal 100019e4 <printf> |
|
} |
|
static inline void exit(unsigned exit_code) |
{ |
volatile register char t1 asm ("r1") = exit_code; |
10001d68: 9c 20 00 01 l.addi r1,r0,1 |
__asm__ __volatile__ ( "\t l.trap 0 "); |
} |
else |
{ |
// Invalid instruction! |
__asm__ __volatile__ ( "\t lf.add.s r0,r0,r0 "); |
10001d6c: c8 00 00 00 lf.add.s r0,r0,r0 |
assert(uvar == 0x0); // .bss |
10001d70: 19 c0 10 00 l.movhi r14,0x1000 |
10001d74: a9 ce 30 04 l.ori r14,r14,0x3004 |
10001d78: 84 6e 00 00 l.lwz r3,0(r14) |
10001d7c: bc 03 00 00 l.sfeqi r3,0 |
10001d80: 0c 00 02 d1 l.bnf 100028c4 <test+0xbd8> |
|
serial_putstr("2. Multiply\n"); |
10001d84: 18 60 10 00 l.movhi r3,0x1000 |
10001d88: a8 63 2d 47 l.ori r3,r3,0x2d47 |
10001d8c: 07 ff ff 64 l.jal 10001b1c <serial_putstr> |
var = var * 3; |
10001d90: 84 62 00 00 l.lwz r3,0(r2) |
10001d94: e0 83 18 00 l.add r4,r3,r3 |
10001d98: e0 64 18 00 l.add r3,r4,r3 |
10001d9c: d4 02 18 00 l.sw 0(r2),r3 |
assert(var == 13980); |
10001da0: 84 62 00 00 l.lwz r3,0(r2) |
10001da4: bc 03 36 9c l.sfeqi r3,13980 |
10001da8: 10 00 00 0e l.bf 10001de0 <test+0xf4> |
10001dac: 18 60 10 00 l.movhi r3,0x1000 |
10001db0: a8 63 2d 54 l.ori r3,r3,0x2d54 |
10001db4: d4 01 18 00 l.sw 0(r1),r3 |
10001db8: 18 60 10 00 l.movhi r3,0x1000 |
10001dbc: a8 63 2d 34 l.ori r3,r3,0x2d34 |
10001dc0: d4 01 18 04 l.sw 4(r1),r3 |
10001dc4: 9c 60 00 2e l.addi r3,r0,46 |
10001dc8: d4 01 18 08 l.sw 8(r1),r3 |
10001dcc: 18 60 10 00 l.movhi r3,0x1000 |
10001dd0: a8 63 2c 74 l.ori r3,r3,0x2c74 |
10001dd4: 07 ff ff 04 l.jal 100019e4 <printf> |
|
} |
|
static inline void exit(unsigned exit_code) |
{ |
volatile register char t1 asm ("r1") = exit_code; |
10001dd8: 9c 20 00 01 l.addi r1,r0,1 |
__asm__ __volatile__ ( "\t l.trap 0 "); |
} |
else |
{ |
// Invalid instruction! |
__asm__ __volatile__ ( "\t lf.add.s r0,r0,r0 "); |
10001ddc: c8 00 00 00 lf.add.s r0,r0,r0 |
var = -1; |
10001de0: 9c 60 ff ff l.addi r3,r0,-1 |
10001de4: d4 02 18 00 l.sw 0(r2),r3 |
var = var * 3; |
10001de8: 84 62 00 00 l.lwz r3,0(r2) |
10001dec: e0 83 18 00 l.add r4,r3,r3 |
10001df0: e0 64 18 00 l.add r3,r4,r3 |
10001df4: d4 02 18 00 l.sw 0(r2),r3 |
assert(var == -3); |
10001df8: 84 62 00 00 l.lwz r3,0(r2) |
10001dfc: bc 03 ff fd l.sfeqi r3,-3 |
10001e00: 10 00 00 0e l.bf 10001e38 <test+0x14c> |
10001e04: 18 60 10 00 l.movhi r3,0x1000 |
10001e08: a8 63 2d 61 l.ori r3,r3,0x2d61 |
10001e0c: d4 01 18 00 l.sw 0(r1),r3 |
10001e10: 18 60 10 00 l.movhi r3,0x1000 |
10001e14: a8 63 2d 34 l.ori r3,r3,0x2d34 |
10001e18: d4 01 18 04 l.sw 4(r1),r3 |
10001e1c: 9c 60 00 31 l.addi r3,r0,49 |
10001e20: d4 01 18 08 l.sw 8(r1),r3 |
10001e24: 18 60 10 00 l.movhi r3,0x1000 |
10001e28: a8 63 2c 74 l.ori r3,r3,0x2c74 |
10001e2c: 07 ff fe ee l.jal 100019e4 <printf> |
|
} |
|
static inline void exit(unsigned exit_code) |
{ |
volatile register char t1 asm ("r1") = exit_code; |
10001e30: 9c 20 00 01 l.addi r1,r0,1 |
__asm__ __volatile__ ( "\t l.trap 0 "); |
} |
else |
{ |
// Invalid instruction! |
__asm__ __volatile__ ( "\t lf.add.s r0,r0,r0 "); |
10001e34: c8 00 00 00 lf.add.s r0,r0,r0 |
var = -5; |
10001e38: 9c 60 ff fb l.addi r3,r0,-5 |
10001e3c: d4 02 18 00 l.sw 0(r2),r3 |
var = var * 13; |
10001e40: 84 62 00 00 l.lwz r3,0(r2) |
10001e44: e0 83 18 00 l.add r4,r3,r3 |
10001e48: e0 84 18 00 l.add r4,r4,r3 |
10001e4c: b8 84 00 02 l.slli r4,r4,0x2 |
10001e50: e0 64 18 00 l.add r3,r4,r3 |
10001e54: d4 02 18 00 l.sw 0(r2),r3 |
assert(var == -65); |
10001e58: 84 62 00 00 l.lwz r3,0(r2) |
10001e5c: bc 03 ff bf l.sfeqi r3,-65 |
10001e60: 10 00 00 0e l.bf 10001e98 <test+0x1ac> |
10001e64: 18 60 10 00 l.movhi r3,0x1000 |
10001e68: a8 63 2d 6b l.ori r3,r3,0x2d6b |
10001e6c: d4 01 18 00 l.sw 0(r1),r3 |
10001e70: 18 60 10 00 l.movhi r3,0x1000 |
10001e74: a8 63 2d 34 l.ori r3,r3,0x2d34 |
10001e78: d4 01 18 04 l.sw 4(r1),r3 |
10001e7c: 9c 60 00 34 l.addi r3,r0,52 |
10001e80: d4 01 18 08 l.sw 8(r1),r3 |
10001e84: 18 60 10 00 l.movhi r3,0x1000 |
10001e88: a8 63 2c 74 l.ori r3,r3,0x2c74 |
10001e8c: 07 ff fe d6 l.jal 100019e4 <printf> |
|
} |
|
static inline void exit(unsigned exit_code) |
{ |
volatile register char t1 asm ("r1") = exit_code; |
10001e90: 9c 20 00 01 l.addi r1,r0,1 |
__asm__ __volatile__ ( "\t l.trap 0 "); |
} |
else |
{ |
// Invalid instruction! |
__asm__ __volatile__ ( "\t lf.add.s r0,r0,r0 "); |
10001e94: c8 00 00 00 lf.add.s r0,r0,r0 |
var = -5; |
10001e98: 9c 60 ff fb l.addi r3,r0,-5 |
var = var * -13; |
10001e9c: 9c 80 ff f3 l.addi r4,r0,-13 |
var = var * 3; |
assert(var == -3); |
var = -5; |
var = var * 13; |
assert(var == -65); |
var = -5; |
10001ea0: d4 02 18 00 l.sw 0(r2),r3 |
var = var * -13; |
10001ea4: 84 62 00 00 l.lwz r3,0(r2) |
10001ea8: 04 00 03 04 l.jal 10002ab8 <__mulsi3> |
10001eac: d4 02 58 00 l.sw 0(r2),r11 |
assert(var == (-5*-13)); |
10001eb0: 84 62 00 00 l.lwz r3,0(r2) |
10001eb4: bc 03 00 41 l.sfeqi r3,65 |
10001eb8: 10 00 00 0e l.bf 10001ef0 <test+0x204> |
10001ebc: 18 60 10 00 l.movhi r3,0x1000 |
10001ec0: a8 63 2d 76 l.ori r3,r3,0x2d76 |
10001ec4: d4 01 18 00 l.sw 0(r1),r3 |
10001ec8: 18 60 10 00 l.movhi r3,0x1000 |
10001ecc: a8 63 2d 34 l.ori r3,r3,0x2d34 |
10001ed0: d4 01 18 04 l.sw 4(r1),r3 |
10001ed4: 9c 60 00 37 l.addi r3,r0,55 |
10001ed8: d4 01 18 08 l.sw 8(r1),r3 |
10001edc: 18 60 10 00 l.movhi r3,0x1000 |
10001ee0: a8 63 2c 74 l.ori r3,r3,0x2c74 |
10001ee4: 07 ff fe c0 l.jal 100019e4 <printf> |
|
} |
|
static inline void exit(unsigned exit_code) |
{ |
volatile register char t1 asm ("r1") = exit_code; |
10001ee8: 9c 20 00 01 l.addi r1,r0,1 |
__asm__ __volatile__ ( "\t l.trap 0 "); |
} |
else |
{ |
// Invalid instruction! |
__asm__ __volatile__ ( "\t lf.add.s r0,r0,r0 "); |
10001eec: c8 00 00 00 lf.add.s r0,r0,r0 |
var = -123123415; |
10001ef0: 18 60 f8 a9 l.movhi r3,0xf8a9 |
var = var * 9664563; |
10001ef4: 18 80 00 93 l.movhi r4,0x93 |
var = var * 13; |
assert(var == -65); |
var = -5; |
var = var * -13; |
assert(var == (-5*-13)); |
var = -123123415; |
10001ef8: a8 63 49 29 l.ori r3,r3,0x4929 |
var = var * 9664563; |
10001efc: a8 84 78 33 l.ori r4,r4,0x7833 |
var = var * 13; |
assert(var == -65); |
var = -5; |
var = var * -13; |
assert(var == (-5*-13)); |
var = -123123415; |
10001f00: d4 02 18 00 l.sw 0(r2),r3 |
var = var * 9664563; |
10001f04: 84 62 00 00 l.lwz r3,0(r2) |
10001f08: 04 00 02 ec l.jal 10002ab8 <__mulsi3> |
assert(var == (-123123415*9664563)); |
10001f0c: 18 80 e6 8f l.movhi r4,0xe68f |
assert(var == -65); |
var = -5; |
var = var * -13; |
assert(var == (-5*-13)); |
var = -123123415; |
var = var * 9664563; |
10001f10: d4 02 58 00 l.sw 0(r2),r11 |
assert(var == (-123123415*9664563)); |
10001f14: a8 84 cb 2b l.ori r4,r4,0xcb2b |
10001f18: 84 62 00 00 l.lwz r3,0(r2) |
10001f1c: e4 03 20 00 l.sfeq r3,r4 |
10001f20: 10 00 00 0e l.bf 10001f58 <test+0x26c> |
10001f24: 18 60 10 00 l.movhi r3,0x1000 |
10001f28: a8 63 2d 86 l.ori r3,r3,0x2d86 |
10001f2c: d4 01 18 00 l.sw 0(r1),r3 |
10001f30: 18 60 10 00 l.movhi r3,0x1000 |
10001f34: a8 63 2d 34 l.ori r3,r3,0x2d34 |
10001f38: d4 01 18 04 l.sw 4(r1),r3 |
10001f3c: 9c 60 00 3a l.addi r3,r0,58 |
10001f40: d4 01 18 08 l.sw 8(r1),r3 |
10001f44: 18 60 10 00 l.movhi r3,0x1000 |
10001f48: a8 63 2c 74 l.ori r3,r3,0x2c74 |
10001f4c: 07 ff fe a6 l.jal 100019e4 <printf> |
|
} |
|
static inline void exit(unsigned exit_code) |
{ |
volatile register char t1 asm ("r1") = exit_code; |
10001f50: 9c 20 00 01 l.addi r1,r0,1 |
__asm__ __volatile__ ( "\t l.trap 0 "); |
} |
else |
{ |
// Invalid instruction! |
__asm__ __volatile__ ( "\t lf.add.s r0,r0,r0 "); |
10001f54: c8 00 00 00 lf.add.s r0,r0,r0 |
|
serial_putstr("3. Divide\n"); |
10001f58: 18 60 10 00 l.movhi r3,0x1000 |
10001f5c: a8 63 2d a2 l.ori r3,r3,0x2da2 |
10001f60: 07 ff fe ef l.jal 10001b1c <serial_putstr> |
var = 13980; |
10001f64: 9c 60 36 9c l.addi r3,r0,13980 |
var = var / 5; |
10001f68: 9c 80 00 05 l.addi r4,r0,5 |
var = -123123415; |
var = var * 9664563; |
assert(var == (-123123415*9664563)); |
|
serial_putstr("3. Divide\n"); |
var = 13980; |
10001f6c: d4 02 18 00 l.sw 0(r2),r3 |
var = var / 5; |
10001f70: 84 62 00 00 l.lwz r3,0(r2) |
10001f74: 04 00 02 74 l.jal 10002944 <__divsi3> |
10001f78: d4 02 58 00 l.sw 0(r2),r11 |
assert(var == 2796); |
10001f7c: 84 62 00 00 l.lwz r3,0(r2) |
10001f80: bc 03 0a ec l.sfeqi r3,2796 |
10001f84: 10 00 00 0e l.bf 10001fbc <test+0x2d0> |
10001f88: 18 60 10 00 l.movhi r3,0x1000 |
10001f8c: a8 63 2d ad l.ori r3,r3,0x2dad |
10001f90: d4 01 18 00 l.sw 0(r1),r3 |
10001f94: 18 60 10 00 l.movhi r3,0x1000 |
10001f98: a8 63 2d 34 l.ori r3,r3,0x2d34 |
10001f9c: d4 01 18 04 l.sw 4(r1),r3 |
10001fa0: 9c 60 00 3f l.addi r3,r0,63 |
10001fa4: d4 01 18 08 l.sw 8(r1),r3 |
10001fa8: 18 60 10 00 l.movhi r3,0x1000 |
10001fac: a8 63 2c 74 l.ori r3,r3,0x2c74 |
10001fb0: 07 ff fe 8d l.jal 100019e4 <printf> |
|
} |
|
static inline void exit(unsigned exit_code) |
{ |
volatile register char t1 asm ("r1") = exit_code; |
10001fb4: 9c 20 00 01 l.addi r1,r0,1 |
__asm__ __volatile__ ( "\t l.trap 0 "); |
} |
else |
{ |
// Invalid instruction! |
__asm__ __volatile__ ( "\t lf.add.s r0,r0,r0 "); |
10001fb8: c8 00 00 00 lf.add.s r0,r0,r0 |
var = var % 100; |
10001fbc: 84 62 00 00 l.lwz r3,0(r2) |
10001fc0: 9c 80 00 64 l.addi r4,r0,100 |
10001fc4: 04 00 02 7a l.jal 100029ac <__modsi3> |
10001fc8: d4 02 58 00 l.sw 0(r2),r11 |
assert(var == 96); |
10001fcc: 84 62 00 00 l.lwz r3,0(r2) |
10001fd0: bc 03 00 60 l.sfeqi r3,96 |
10001fd4: 10 00 00 0e l.bf 1000200c <test+0x320> |
10001fd8: 18 60 10 00 l.movhi r3,0x1000 |
10001fdc: a8 63 2d b9 l.ori r3,r3,0x2db9 |
10001fe0: d4 01 18 00 l.sw 0(r1),r3 |
10001fe4: 18 60 10 00 l.movhi r3,0x1000 |
10001fe8: a8 63 2d 34 l.ori r3,r3,0x2d34 |
10001fec: d4 01 18 04 l.sw 4(r1),r3 |
10001ff0: 9c 60 00 41 l.addi r3,r0,65 |
10001ff4: d4 01 18 08 l.sw 8(r1),r3 |
10001ff8: 18 60 10 00 l.movhi r3,0x1000 |
10001ffc: a8 63 2c 74 l.ori r3,r3,0x2c74 |
10002000: 07 ff fe 79 l.jal 100019e4 <printf> |
|
} |
|
static inline void exit(unsigned exit_code) |
{ |
volatile register char t1 asm ("r1") = exit_code; |
10002004: 9c 20 00 01 l.addi r1,r0,1 |
__asm__ __volatile__ ( "\t l.trap 0 "); |
} |
else |
{ |
// Invalid instruction! |
__asm__ __volatile__ ( "\t lf.add.s r0,r0,r0 "); |
10002008: c8 00 00 00 lf.add.s r0,r0,r0 |
var = -1273; |
1000200c: 9c 60 fb 07 l.addi r3,r0,-1273 |
var = var / 19; |
10002010: 9c 80 00 13 l.addi r4,r0,19 |
var = 13980; |
var = var / 5; |
assert(var == 2796); |
var = var % 100; |
assert(var == 96); |
var = -1273; |
10002014: d4 02 18 00 l.sw 0(r2),r3 |
var = var / 19; |
10002018: 84 62 00 00 l.lwz r3,0(r2) |
1000201c: 04 00 02 4a l.jal 10002944 <__divsi3> |
10002020: d4 02 58 00 l.sw 0(r2),r11 |
assert(var == -67); |
10002024: 84 62 00 00 l.lwz r3,0(r2) |
10002028: bc 03 ff bd l.sfeqi r3,-67 |
1000202c: 10 00 00 0e l.bf 10002064 <test+0x378> |
10002030: 18 60 10 00 l.movhi r3,0x1000 |
10002034: a8 63 2d c3 l.ori r3,r3,0x2dc3 |
10002038: d4 01 18 00 l.sw 0(r1),r3 |
1000203c: 18 60 10 00 l.movhi r3,0x1000 |
10002040: a8 63 2d 34 l.ori r3,r3,0x2d34 |
10002044: d4 01 18 04 l.sw 4(r1),r3 |
10002048: 9c 60 00 44 l.addi r3,r0,68 |
1000204c: d4 01 18 08 l.sw 8(r1),r3 |
10002050: 18 60 10 00 l.movhi r3,0x1000 |
10002054: a8 63 2c 74 l.ori r3,r3,0x2c74 |
10002058: 07 ff fe 63 l.jal 100019e4 <printf> |
|
} |
|
static inline void exit(unsigned exit_code) |
{ |
volatile register char t1 asm ("r1") = exit_code; |
1000205c: 9c 20 00 01 l.addi r1,r0,1 |
__asm__ __volatile__ ( "\t l.trap 0 "); |
} |
else |
{ |
// Invalid instruction! |
__asm__ __volatile__ ( "\t lf.add.s r0,r0,r0 "); |
10002060: c8 00 00 00 lf.add.s r0,r0,r0 |
|
serial_putstr("4. Shift left\n"); |
10002064: 18 60 10 00 l.movhi r3,0x1000 |
var = 0x1; |
10002068: 9e 40 00 01 l.addi r18,r0,1 |
assert(var == 96); |
var = -1273; |
var = var / 19; |
assert(var == -67); |
|
serial_putstr("4. Shift left\n"); |
1000206c: a8 63 2d ce l.ori r3,r3,0x2dce |
10002070: 07 ff fe ab l.jal 10001b1c <serial_putstr> |
var = 0x1; |
10002074: d4 02 90 00 l.sw 0(r2),r18 |
var <<= 31; |
assert(var == 0x80000000); |
10002078: 18 80 80 00 l.movhi r4,0x8000 |
var = var / 19; |
assert(var == -67); |
|
serial_putstr("4. Shift left\n"); |
var = 0x1; |
var <<= 31; |
1000207c: 84 62 00 00 l.lwz r3,0(r2) |
10002080: b8 63 00 1f l.slli r3,r3,0x1f |
10002084: d4 02 18 00 l.sw 0(r2),r3 |
assert(var == 0x80000000); |
10002088: 84 62 00 00 l.lwz r3,0(r2) |
1000208c: e4 03 20 00 l.sfeq r3,r4 |
10002090: 10 00 00 0e l.bf 100020c8 <test+0x3dc> |
10002094: 18 60 10 00 l.movhi r3,0x1000 |
10002098: a8 63 2d dd l.ori r3,r3,0x2ddd |
1000209c: d4 01 18 00 l.sw 0(r1),r3 |
100020a0: 18 60 10 00 l.movhi r3,0x1000 |
100020a4: a8 63 2d 34 l.ori r3,r3,0x2d34 |
100020a8: d4 01 18 04 l.sw 4(r1),r3 |
100020ac: 9c 60 00 49 l.addi r3,r0,73 |
100020b0: d4 01 18 08 l.sw 8(r1),r3 |
100020b4: 18 60 10 00 l.movhi r3,0x1000 |
100020b8: a8 63 2c 74 l.ori r3,r3,0x2c74 |
100020bc: 07 ff fe 4a l.jal 100019e4 <printf> |
|
} |
|
static inline void exit(unsigned exit_code) |
{ |
volatile register char t1 asm ("r1") = exit_code; |
100020c0: a8 32 00 00 l.ori r1,r18,0x0 |
__asm__ __volatile__ ( "\t l.trap 0 "); |
} |
else |
{ |
// Invalid instruction! |
__asm__ __volatile__ ( "\t lf.add.s r0,r0,r0 "); |
100020c4: c8 00 00 00 lf.add.s r0,r0,r0 |
|
serial_putstr("5. Shift right\n"); |
100020c8: 18 60 10 00 l.movhi r3,0x1000 |
100020cc: a8 63 2d ef l.ori r3,r3,0x2def |
100020d0: 07 ff fe 93 l.jal 10001b1c <serial_putstr> |
uvar = 0x80000000; |
100020d4: 18 60 80 00 l.movhi r3,0x8000 |
uvar >>= 1; |
assert(uvar == 0x40000000); |
100020d8: 18 80 40 00 l.movhi r4,0x4000 |
var = 0x1; |
var <<= 31; |
assert(var == 0x80000000); |
|
serial_putstr("5. Shift right\n"); |
uvar = 0x80000000; |
100020dc: d4 0e 18 00 l.sw 0(r14),r3 |
uvar >>= 1; |
100020e0: 84 6e 00 00 l.lwz r3,0(r14) |
100020e4: b8 63 00 41 l.srli r3,r3,0x1 |
100020e8: d4 0e 18 00 l.sw 0(r14),r3 |
assert(uvar == 0x40000000); |
100020ec: 84 6e 00 00 l.lwz r3,0(r14) |
100020f0: e4 03 20 00 l.sfeq r3,r4 |
100020f4: 10 00 00 0e l.bf 1000212c <test+0x440> |
100020f8: 18 60 10 00 l.movhi r3,0x1000 |
100020fc: a8 63 2d ff l.ori r3,r3,0x2dff |
10002100: d4 01 18 00 l.sw 0(r1),r3 |
10002104: 18 60 10 00 l.movhi r3,0x1000 |
10002108: a8 63 2d 34 l.ori r3,r3,0x2d34 |
1000210c: d4 01 18 04 l.sw 4(r1),r3 |
10002110: 9c 60 00 4e l.addi r3,r0,78 |
10002114: d4 01 18 08 l.sw 8(r1),r3 |
10002118: 18 60 10 00 l.movhi r3,0x1000 |
1000211c: a8 63 2c 74 l.ori r3,r3,0x2c74 |
10002120: 07 ff fe 31 l.jal 100019e4 <printf> |
|
} |
|
static inline void exit(unsigned exit_code) |
{ |
volatile register char t1 asm ("r1") = exit_code; |
10002124: 9c 20 00 01 l.addi r1,r0,1 |
__asm__ __volatile__ ( "\t l.trap 0 "); |
} |
else |
{ |
// Invalid instruction! |
__asm__ __volatile__ ( "\t lf.add.s r0,r0,r0 "); |
10002128: c8 00 00 00 lf.add.s r0,r0,r0 |
uvar >>= 30; |
1000212c: 84 6e 00 00 l.lwz r3,0(r14) |
10002130: b8 63 00 5e l.srli r3,r3,0x1e |
10002134: d4 0e 18 00 l.sw 0(r14),r3 |
assert(uvar == 0x00000001); |
10002138: 84 6e 00 00 l.lwz r3,0(r14) |
1000213c: bc 03 00 01 l.sfeqi r3,1 |
10002140: 10 00 00 0e l.bf 10002178 <test+0x48c> |
10002144: 18 60 10 00 l.movhi r3,0x1000 |
10002148: a8 63 2e 12 l.ori r3,r3,0x2e12 |
1000214c: d4 01 18 00 l.sw 0(r1),r3 |
10002150: 18 60 10 00 l.movhi r3,0x1000 |
10002154: a8 63 2d 34 l.ori r3,r3,0x2d34 |
10002158: d4 01 18 04 l.sw 4(r1),r3 |
1000215c: 9c 60 00 50 l.addi r3,r0,80 |
10002160: d4 01 18 08 l.sw 8(r1),r3 |
10002164: 18 60 10 00 l.movhi r3,0x1000 |
10002168: a8 63 2c 74 l.ori r3,r3,0x2c74 |
1000216c: 07 ff fe 1e l.jal 100019e4 <printf> |
|
} |
|
static inline void exit(unsigned exit_code) |
{ |
volatile register char t1 asm ("r1") = exit_code; |
10002170: 9c 20 00 01 l.addi r1,r0,1 |
__asm__ __volatile__ ( "\t l.trap 0 "); |
} |
else |
{ |
// Invalid instruction! |
__asm__ __volatile__ ( "\t lf.add.s r0,r0,r0 "); |
10002174: c8 00 00 00 lf.add.s r0,r0,r0 |
|
serial_putstr("6. Shift right arithmetic\n"); |
10002178: 18 60 10 00 l.movhi r3,0x1000 |
1000217c: a8 63 2e 25 l.ori r3,r3,0x2e25 |
10002180: 07 ff fe 67 l.jal 10001b1c <serial_putstr> |
var = 0x80000000; |
10002184: 18 60 80 00 l.movhi r3,0x8000 |
var >>= 1; |
assert(var == 0xC0000000); |
10002188: 18 80 c0 00 l.movhi r4,0xc000 |
assert(uvar == 0x40000000); |
uvar >>= 30; |
assert(uvar == 0x00000001); |
|
serial_putstr("6. Shift right arithmetic\n"); |
var = 0x80000000; |
1000218c: d4 02 18 00 l.sw 0(r2),r3 |
var >>= 1; |
10002190: 84 62 00 00 l.lwz r3,0(r2) |
10002194: b8 63 00 81 l.srai r3,r3,0x1 |
10002198: d4 02 18 00 l.sw 0(r2),r3 |
assert(var == 0xC0000000); |
1000219c: 84 62 00 00 l.lwz r3,0(r2) |
100021a0: e4 03 20 00 l.sfeq r3,r4 |
100021a4: 10 00 00 0e l.bf 100021dc <test+0x4f0> |
100021a8: 18 60 10 00 l.movhi r3,0x1000 |
100021ac: a8 63 2e 40 l.ori r3,r3,0x2e40 |
100021b0: d4 01 18 00 l.sw 0(r1),r3 |
100021b4: 18 60 10 00 l.movhi r3,0x1000 |
100021b8: a8 63 2d 34 l.ori r3,r3,0x2d34 |
100021bc: d4 01 18 04 l.sw 4(r1),r3 |
100021c0: 9c 60 00 55 l.addi r3,r0,85 |
100021c4: d4 01 18 08 l.sw 8(r1),r3 |
100021c8: 18 60 10 00 l.movhi r3,0x1000 |
100021cc: a8 63 2c 74 l.ori r3,r3,0x2c74 |
100021d0: 07 ff fe 05 l.jal 100019e4 <printf> |
|
} |
|
static inline void exit(unsigned exit_code) |
{ |
volatile register char t1 asm ("r1") = exit_code; |
100021d4: 9c 20 00 01 l.addi r1,r0,1 |
__asm__ __volatile__ ( "\t l.trap 0 "); |
} |
else |
{ |
// Invalid instruction! |
__asm__ __volatile__ ( "\t lf.add.s r0,r0,r0 "); |
100021d8: c8 00 00 00 lf.add.s r0,r0,r0 |
|
serial_putstr("7. Signed comparision\n"); |
100021dc: 18 60 10 00 l.movhi r3,0x1000 |
100021e0: a8 63 2e 52 l.ori r3,r3,0x2e52 |
100021e4: 07 ff fe 4e l.jal 10001b1c <serial_putstr> |
var = -1; |
100021e8: 9c 60 ff ff l.addi r3,r0,-1 |
100021ec: d4 02 18 00 l.sw 0(r2),r3 |
assert(var < 1); |
100021f0: 84 62 00 00 l.lwz r3,0(r2) |
100021f4: bd a3 00 00 l.sflesi r3,0 |
100021f8: 10 00 00 0e l.bf 10002230 <test+0x544> |
100021fc: 18 60 10 00 l.movhi r3,0x1000 |
10002200: a8 63 2e 69 l.ori r3,r3,0x2e69 |
10002204: d4 01 18 00 l.sw 0(r1),r3 |
10002208: 18 60 10 00 l.movhi r3,0x1000 |
1000220c: a8 63 2d 34 l.ori r3,r3,0x2d34 |
10002210: d4 01 18 04 l.sw 4(r1),r3 |
10002214: 9c 60 00 59 l.addi r3,r0,89 |
10002218: d4 01 18 08 l.sw 8(r1),r3 |
1000221c: 18 60 10 00 l.movhi r3,0x1000 |
10002220: a8 63 2c 74 l.ori r3,r3,0x2c74 |
10002224: 07 ff fd f0 l.jal 100019e4 <printf> |
|
} |
|
static inline void exit(unsigned exit_code) |
{ |
volatile register char t1 asm ("r1") = exit_code; |
10002228: 9c 20 00 01 l.addi r1,r0,1 |
__asm__ __volatile__ ( "\t l.trap 0 "); |
} |
else |
{ |
// Invalid instruction! |
__asm__ __volatile__ ( "\t lf.add.s r0,r0,r0 "); |
1000222c: c8 00 00 00 lf.add.s r0,r0,r0 |
x = 10; |
assert(var < x); |
10002230: 84 62 00 00 l.lwz r3,0(r2) |
10002234: bd a3 00 09 l.sflesi r3,9 |
10002238: 0c 00 01 95 l.bnf 1000288c <test+0xba0> |
assert(!(var > x)); |
1000223c: 84 62 00 00 l.lwz r3,0(r2) |
10002240: bd a3 00 0a l.sflesi r3,10 |
10002244: 0c 00 01 84 l.bnf 10002854 <test+0xb68> |
x = -3; |
assert(var > x); |
10002248: 84 62 00 00 l.lwz r3,0(r2) |
1000224c: bd 63 ff fe l.sfgesi r3,-2 |
10002250: 0c 00 01 73 l.bnf 1000281c <test+0xb30> |
assert(x <= var); |
10002254: 84 42 00 00 l.lwz r2,0(r2) |
10002258: bd 62 ff fd l.sfgesi r2,-3 |
1000225c: 0c 00 01 62 l.bnf 100027e4 <test+0xaf8> |
|
serial_putstr("8. Word access\n"); |
10002260: 18 60 10 00 l.movhi r3,0x1000 |
uvar = 0x12345678; |
10002264: 18 40 12 34 l.movhi r2,0x1234 |
assert(!(var > x)); |
x = -3; |
assert(var > x); |
assert(x <= var); |
|
serial_putstr("8. Word access\n"); |
10002268: a8 63 2e 95 l.ori r3,r3,0x2e95 |
uvar = 0x12345678; |
1000226c: a8 42 56 78 l.ori r2,r2,0x5678 |
assert(!(var > x)); |
x = -3; |
assert(var > x); |
assert(x <= var); |
|
serial_putstr("8. Word access\n"); |
10002270: 07 ff fe 2b l.jal 10001b1c <serial_putstr> |
uvar = 0x12345678; |
assert(uvar == 0x12345678); |
10002274: 18 60 12 34 l.movhi r3,0x1234 |
x = -3; |
assert(var > x); |
assert(x <= var); |
|
serial_putstr("8. Word access\n"); |
uvar = 0x12345678; |
10002278: d4 0e 10 00 l.sw 0(r14),r2 |
assert(uvar == 0x12345678); |
1000227c: a8 63 56 78 l.ori r3,r3,0x5678 |
10002280: 84 4e 00 00 l.lwz r2,0(r14) |
10002284: e4 02 18 00 l.sfeq r2,r3 |
10002288: 10 00 00 0e l.bf 100022c0 <test+0x5d4> |
1000228c: 18 40 10 00 l.movhi r2,0x1000 |
10002290: 18 60 10 00 l.movhi r3,0x1000 |
10002294: a8 42 2e a5 l.ori r2,r2,0x2ea5 |
10002298: a8 63 2c 74 l.ori r3,r3,0x2c74 |
1000229c: d4 01 10 00 l.sw 0(r1),r2 |
100022a0: 18 40 10 00 l.movhi r2,0x1000 |
100022a4: a8 42 2d 34 l.ori r2,r2,0x2d34 |
100022a8: d4 01 10 04 l.sw 4(r1),r2 |
100022ac: 9c 40 00 63 l.addi r2,r0,99 |
100022b0: d4 01 10 08 l.sw 8(r1),r2 |
100022b4: 07 ff fd cc l.jal 100019e4 <printf> |
|
} |
|
static inline void exit(unsigned exit_code) |
{ |
volatile register char t1 asm ("r1") = exit_code; |
100022b8: 9c 20 00 01 l.addi r1,r0,1 |
__asm__ __volatile__ ( "\t l.trap 0 "); |
} |
else |
{ |
// Invalid instruction! |
__asm__ __volatile__ ( "\t lf.add.s r0,r0,r0 "); |
100022bc: c8 00 00 00 lf.add.s r0,r0,r0 |
sw = uvar; |
100022c0: 84 4e 00 00 l.lwz r2,0(r14) |
assert(sw == 0x5678); |
100022c4: a4 42 ff ff l.andi r2,r2,0xffff |
100022c8: bc 02 56 78 l.sfeqi r2,22136 |
100022cc: 10 00 00 0e l.bf 10002304 <test+0x618> |
100022d0: 18 40 10 00 l.movhi r2,0x1000 |
100022d4: 18 60 10 00 l.movhi r3,0x1000 |
100022d8: a8 42 2e b8 l.ori r2,r2,0x2eb8 |
100022dc: a8 63 2c 74 l.ori r3,r3,0x2c74 |
100022e0: d4 01 10 00 l.sw 0(r1),r2 |
100022e4: 18 40 10 00 l.movhi r2,0x1000 |
100022e8: a8 42 2d 34 l.ori r2,r2,0x2d34 |
100022ec: d4 01 10 04 l.sw 4(r1),r2 |
100022f0: 9c 40 00 65 l.addi r2,r0,101 |
100022f4: d4 01 10 08 l.sw 8(r1),r2 |
100022f8: 07 ff fd bb l.jal 100019e4 <printf> |
|
} |
|
static inline void exit(unsigned exit_code) |
{ |
volatile register char t1 asm ("r1") = exit_code; |
100022fc: 9c 20 00 01 l.addi r1,r0,1 |
__asm__ __volatile__ ( "\t l.trap 0 "); |
} |
else |
{ |
// Invalid instruction! |
__asm__ __volatile__ ( "\t lf.add.s r0,r0,r0 "); |
10002300: c8 00 00 00 lf.add.s r0,r0,r0 |
psw = &uvar; |
assert(*psw++ == 0x1234); |
10002304: 94 4e 00 00 l.lhz r2,0(r14) |
10002308: bc 02 12 34 l.sfeqi r2,4660 |
1000230c: 10 00 00 0e l.bf 10002344 <test+0x658> |
10002310: 18 40 10 00 l.movhi r2,0x1000 |
10002314: 18 60 10 00 l.movhi r3,0x1000 |
10002318: a8 42 2e c5 l.ori r2,r2,0x2ec5 |
1000231c: a8 63 2c 74 l.ori r3,r3,0x2c74 |
10002320: d4 01 10 00 l.sw 0(r1),r2 |
10002324: 18 40 10 00 l.movhi r2,0x1000 |
10002328: a8 42 2d 34 l.ori r2,r2,0x2d34 |
1000232c: d4 01 10 04 l.sw 4(r1),r2 |
10002330: 9c 40 00 67 l.addi r2,r0,103 |
10002334: d4 01 10 08 l.sw 8(r1),r2 |
10002338: 07 ff fd ab l.jal 100019e4 <printf> |
|
} |
|
static inline void exit(unsigned exit_code) |
{ |
volatile register char t1 asm ("r1") = exit_code; |
1000233c: 9c 20 00 01 l.addi r1,r0,1 |
__asm__ __volatile__ ( "\t l.trap 0 "); |
} |
else |
{ |
// Invalid instruction! |
__asm__ __volatile__ ( "\t lf.add.s r0,r0,r0 "); |
10002340: c8 00 00 00 lf.add.s r0,r0,r0 |
assert(*psw++ == 0x5678); |
10002344: 94 4e 00 02 l.lhz r2,2(r14) |
10002348: bc 02 56 78 l.sfeqi r2,22136 |
1000234c: 10 00 01 1f l.bf 100027c8 <test+0xadc> |
10002350: 9c 60 00 68 l.addi r3,r0,104 |
10002354: 1a 40 10 00 l.movhi r18,0x1000 |
10002358: 18 40 10 00 l.movhi r2,0x1000 |
1000235c: d4 01 18 08 l.sw 8(r1),r3 |
10002360: aa 52 2e d6 l.ori r18,r18,0x2ed6 |
10002364: a8 42 2d 34 l.ori r2,r2,0x2d34 |
10002368: 18 60 10 00 l.movhi r3,0x1000 |
1000236c: d4 01 90 00 l.sw 0(r1),r18 |
10002370: d4 01 10 04 l.sw 4(r1),r2 |
10002374: a8 63 2c 74 l.ori r3,r3,0x2c74 |
10002378: 07 ff fd 9b l.jal 100019e4 <printf> |
|
} |
|
static inline void exit(unsigned exit_code) |
{ |
volatile register char t1 asm ("r1") = exit_code; |
1000237c: 9c 20 00 01 l.addi r1,r0,1 |
__asm__ __volatile__ ( "\t l.trap 0 "); |
} |
else |
{ |
// Invalid instruction! |
__asm__ __volatile__ ( "\t lf.add.s r0,r0,r0 "); |
10002380: c8 00 00 00 lf.add.s r0,r0,r0 |
10002384: 94 6e 00 02 l.lhz r3,2(r14) |
psw = &uvar; |
*psw = 0xcafe; |
10002388: 9c 80 ca fe l.addi r4,r0,-13570 |
assert(*psw++ == 0xcafe); |
assert(*psw++ == 0x5678); |
1000238c: bc 03 56 78 l.sfeqi r3,22136 |
assert(sw == 0x5678); |
psw = &uvar; |
assert(*psw++ == 0x1234); |
assert(*psw++ == 0x5678); |
psw = &uvar; |
*psw = 0xcafe; |
10002390: dc 0e 20 00 l.sh 0(r14),r4 |
assert(*psw++ == 0xcafe); |
assert(*psw++ == 0x5678); |
10002394: 10 00 01 11 l.bf 100027d8 <test+0xaec> |
10002398: 9c 60 00 6c l.addi r3,r0,108 |
1000239c: d4 01 90 00 l.sw 0(r1),r18 |
100023a0: d4 01 18 08 l.sw 8(r1),r3 |
100023a4: 18 60 10 00 l.movhi r3,0x1000 |
100023a8: d4 01 10 04 l.sw 4(r1),r2 |
100023ac: a8 63 2c 74 l.ori r3,r3,0x2c74 |
100023b0: 07 ff fd 8d l.jal 100019e4 <printf> |
|
} |
|
static inline void exit(unsigned exit_code) |
{ |
volatile register char t1 asm ("r1") = exit_code; |
100023b4: 9c 20 00 01 l.addi r1,r0,1 |
__asm__ __volatile__ ( "\t l.trap 0 "); |
} |
else |
{ |
// Invalid instruction! |
__asm__ __volatile__ ( "\t lf.add.s r0,r0,r0 "); |
100023b8: c8 00 00 00 lf.add.s r0,r0,r0 |
psw = &uvar; |
*(++psw) = 0xbabe; |
100023bc: 9c 80 ba be l.addi r4,r0,-17730 |
100023c0: 94 6e 00 00 l.lhz r3,0(r14) |
100023c4: dc 0e 20 02 l.sh 2(r14),r4 |
psw = &uvar; |
assert(*psw++ == 0xcafe); |
100023c8: a8 80 ca fe l.ori r4,r0,0xcafe |
100023cc: e4 23 20 00 l.sfne r3,r4 |
100023d0: 0c 00 00 1b l.bnf 1000243c <test+0x750> |
100023d4: 18 60 10 00 l.movhi r3,0x1000 |
100023d8: d4 01 10 04 l.sw 4(r1),r2 |
100023dc: a8 63 2e e7 l.ori r3,r3,0x2ee7 |
100023e0: d4 01 18 00 l.sw 0(r1),r3 |
100023e4: 9c 60 00 70 l.addi r3,r0,112 |
100023e8: d4 01 18 08 l.sw 8(r1),r3 |
100023ec: 18 60 10 00 l.movhi r3,0x1000 |
100023f0: a8 63 2c 74 l.ori r3,r3,0x2c74 |
100023f4: 07 ff fd 7c l.jal 100019e4 <printf> |
|
} |
|
static inline void exit(unsigned exit_code) |
{ |
volatile register char t1 asm ("r1") = exit_code; |
100023f8: 9c 20 00 01 l.addi r1,r0,1 |
__asm__ __volatile__ ( "\t l.trap 0 "); |
} |
else |
{ |
// Invalid instruction! |
__asm__ __volatile__ ( "\t lf.add.s r0,r0,r0 "); |
100023fc: c8 00 00 00 lf.add.s r0,r0,r0 |
assert(*psw++ == 0xbabe); |
10002400: a8 80 ba be l.ori r4,r0,0xbabe |
10002404: 94 6e 00 02 l.lhz r3,2(r14) |
10002408: e4 03 20 00 l.sfeq r3,r4 |
1000240c: 10 00 00 0c l.bf 1000243c <test+0x750> |
10002410: 18 60 10 00 l.movhi r3,0x1000 |
10002414: d4 01 10 04 l.sw 4(r1),r2 |
10002418: a8 63 2e f8 l.ori r3,r3,0x2ef8 |
1000241c: 9c 40 00 71 l.addi r2,r0,113 |
10002420: d4 01 18 00 l.sw 0(r1),r3 |
10002424: 18 60 10 00 l.movhi r3,0x1000 |
10002428: d4 01 10 08 l.sw 8(r1),r2 |
1000242c: a8 63 2c 74 l.ori r3,r3,0x2c74 |
10002430: 07 ff fd 6d l.jal 100019e4 <printf> |
|
} |
|
static inline void exit(unsigned exit_code) |
{ |
volatile register char t1 asm ("r1") = exit_code; |
10002434: 9c 20 00 01 l.addi r1,r0,1 |
__asm__ __volatile__ ( "\t l.trap 0 "); |
} |
else |
{ |
// Invalid instruction! |
__asm__ __volatile__ ( "\t lf.add.s r0,r0,r0 "); |
10002438: c8 00 00 00 lf.add.s r0,r0,r0 |
|
serial_putstr("9. Byte access\n"); |
1000243c: 18 60 10 00 l.movhi r3,0x1000 |
uvar = 0x12345678; |
10002440: 18 40 12 34 l.movhi r2,0x1234 |
*(++psw) = 0xbabe; |
psw = &uvar; |
assert(*psw++ == 0xcafe); |
assert(*psw++ == 0xbabe); |
|
serial_putstr("9. Byte access\n"); |
10002444: a8 63 2f 09 l.ori r3,r3,0x2f09 |
uvar = 0x12345678; |
10002448: a8 42 56 78 l.ori r2,r2,0x5678 |
*(++psw) = 0xbabe; |
psw = &uvar; |
assert(*psw++ == 0xcafe); |
assert(*psw++ == 0xbabe); |
|
serial_putstr("9. Byte access\n"); |
1000244c: 07 ff fd b4 l.jal 10001b1c <serial_putstr> |
uvar = 0x12345678; |
assert(uvar == 0x12345678); |
10002450: 18 60 12 34 l.movhi r3,0x1234 |
psw = &uvar; |
assert(*psw++ == 0xcafe); |
assert(*psw++ == 0xbabe); |
|
serial_putstr("9. Byte access\n"); |
uvar = 0x12345678; |
10002454: d4 0e 10 00 l.sw 0(r14),r2 |
assert(uvar == 0x12345678); |
10002458: a8 63 56 78 l.ori r3,r3,0x5678 |
1000245c: 84 4e 00 00 l.lwz r2,0(r14) |
10002460: e4 02 18 00 l.sfeq r2,r3 |
10002464: 10 00 00 0e l.bf 1000249c <test+0x7b0> |
10002468: 18 40 10 00 l.movhi r2,0x1000 |
1000246c: 18 60 10 00 l.movhi r3,0x1000 |
10002470: a8 42 2e a5 l.ori r2,r2,0x2ea5 |
10002474: a8 63 2c 74 l.ori r3,r3,0x2c74 |
10002478: d4 01 10 00 l.sw 0(r1),r2 |
1000247c: 18 40 10 00 l.movhi r2,0x1000 |
10002480: a8 42 2d 34 l.ori r2,r2,0x2d34 |
10002484: d4 01 10 04 l.sw 4(r1),r2 |
10002488: 9c 40 00 75 l.addi r2,r0,117 |
1000248c: d4 01 10 08 l.sw 8(r1),r2 |
10002490: 07 ff fd 55 l.jal 100019e4 <printf> |
|
} |
|
static inline void exit(unsigned exit_code) |
{ |
volatile register char t1 asm ("r1") = exit_code; |
10002494: 9c 20 00 01 l.addi r1,r0,1 |
__asm__ __volatile__ ( "\t l.trap 0 "); |
} |
else |
{ |
// Invalid instruction! |
__asm__ __volatile__ ( "\t lf.add.s r0,r0,r0 "); |
10002498: c8 00 00 00 lf.add.s r0,r0,r0 |
sb = uvar; |
1000249c: 84 4e 00 00 l.lwz r2,0(r14) |
assert(sb == 0x78); |
100024a0: a4 42 00 ff l.andi r2,r2,0xff |
100024a4: bc 02 00 78 l.sfeqi r2,120 |
100024a8: 10 00 00 0e l.bf 100024e0 <test+0x7f4> |
100024ac: 18 40 10 00 l.movhi r2,0x1000 |
100024b0: 18 60 10 00 l.movhi r3,0x1000 |
100024b4: a8 42 2f 19 l.ori r2,r2,0x2f19 |
100024b8: a8 63 2c 74 l.ori r3,r3,0x2c74 |
100024bc: d4 01 10 00 l.sw 0(r1),r2 |
100024c0: 18 40 10 00 l.movhi r2,0x1000 |
100024c4: a8 42 2d 34 l.ori r2,r2,0x2d34 |
100024c8: d4 01 10 04 l.sw 4(r1),r2 |
100024cc: 9c 40 00 77 l.addi r2,r0,119 |
100024d0: d4 01 10 08 l.sw 8(r1),r2 |
100024d4: 07 ff fd 44 l.jal 100019e4 <printf> |
|
} |
|
static inline void exit(unsigned exit_code) |
{ |
volatile register char t1 asm ("r1") = exit_code; |
100024d8: 9c 20 00 01 l.addi r1,r0,1 |
__asm__ __volatile__ ( "\t l.trap 0 "); |
} |
else |
{ |
// Invalid instruction! |
__asm__ __volatile__ ( "\t lf.add.s r0,r0,r0 "); |
100024dc: c8 00 00 00 lf.add.s r0,r0,r0 |
psb = &uvar; |
assert(*psb++ == 0x12); |
100024e0: 8c 4e 00 00 l.lbz r2,0(r14) |
100024e4: bc 02 00 12 l.sfeqi r2,18 |
100024e8: 10 00 00 0e l.bf 10002520 <test+0x834> |
100024ec: 18 40 10 00 l.movhi r2,0x1000 |
100024f0: 18 60 10 00 l.movhi r3,0x1000 |
100024f4: a8 42 2f 24 l.ori r2,r2,0x2f24 |
100024f8: a8 63 2c 74 l.ori r3,r3,0x2c74 |
100024fc: d4 01 10 00 l.sw 0(r1),r2 |
10002500: 18 40 10 00 l.movhi r2,0x1000 |
10002504: a8 42 2d 34 l.ori r2,r2,0x2d34 |
10002508: d4 01 10 04 l.sw 4(r1),r2 |
1000250c: 9c 40 00 79 l.addi r2,r0,121 |
10002510: d4 01 10 08 l.sw 8(r1),r2 |
10002514: 07 ff fd 34 l.jal 100019e4 <printf> |
|
} |
|
static inline void exit(unsigned exit_code) |
{ |
volatile register char t1 asm ("r1") = exit_code; |
10002518: 9c 20 00 01 l.addi r1,r0,1 |
__asm__ __volatile__ ( "\t l.trap 0 "); |
} |
else |
{ |
// Invalid instruction! |
__asm__ __volatile__ ( "\t lf.add.s r0,r0,r0 "); |
1000251c: c8 00 00 00 lf.add.s r0,r0,r0 |
assert(*psb++ == 0x34); |
10002520: 8c 4e 00 01 l.lbz r2,1(r14) |
10002524: bc 02 00 34 l.sfeqi r2,52 |
10002528: 10 00 00 0e l.bf 10002560 <test+0x874> |
1000252c: 18 40 10 00 l.movhi r2,0x1000 |
10002530: 18 60 10 00 l.movhi r3,0x1000 |
10002534: a8 42 2f 33 l.ori r2,r2,0x2f33 |
10002538: a8 63 2c 74 l.ori r3,r3,0x2c74 |
1000253c: d4 01 10 00 l.sw 0(r1),r2 |
10002540: 18 40 10 00 l.movhi r2,0x1000 |
10002544: a8 42 2d 34 l.ori r2,r2,0x2d34 |
10002548: d4 01 10 04 l.sw 4(r1),r2 |
1000254c: 9c 40 00 7a l.addi r2,r0,122 |
10002550: d4 01 10 08 l.sw 8(r1),r2 |
10002554: 07 ff fd 24 l.jal 100019e4 <printf> |
|
} |
|
static inline void exit(unsigned exit_code) |
{ |
volatile register char t1 asm ("r1") = exit_code; |
10002558: 9c 20 00 01 l.addi r1,r0,1 |
__asm__ __volatile__ ( "\t l.trap 0 "); |
} |
else |
{ |
// Invalid instruction! |
__asm__ __volatile__ ( "\t lf.add.s r0,r0,r0 "); |
1000255c: c8 00 00 00 lf.add.s r0,r0,r0 |
assert(*psb++ == 0x56); |
10002560: 8c 4e 00 02 l.lbz r2,2(r14) |
10002564: bc 02 00 56 l.sfeqi r2,86 |
10002568: 10 00 00 0e l.bf 100025a0 <test+0x8b4> |
1000256c: 18 40 10 00 l.movhi r2,0x1000 |
10002570: 18 60 10 00 l.movhi r3,0x1000 |
10002574: a8 42 2f 42 l.ori r2,r2,0x2f42 |
10002578: a8 63 2c 74 l.ori r3,r3,0x2c74 |
1000257c: d4 01 10 00 l.sw 0(r1),r2 |
10002580: 18 40 10 00 l.movhi r2,0x1000 |
10002584: a8 42 2d 34 l.ori r2,r2,0x2d34 |
10002588: d4 01 10 04 l.sw 4(r1),r2 |
1000258c: 9c 40 00 7b l.addi r2,r0,123 |
10002590: d4 01 10 08 l.sw 8(r1),r2 |
10002594: 07 ff fd 14 l.jal 100019e4 <printf> |
|
} |
|
static inline void exit(unsigned exit_code) |
{ |
volatile register char t1 asm ("r1") = exit_code; |
10002598: 9c 20 00 01 l.addi r1,r0,1 |
__asm__ __volatile__ ( "\t l.trap 0 "); |
} |
else |
{ |
// Invalid instruction! |
__asm__ __volatile__ ( "\t lf.add.s r0,r0,r0 "); |
1000259c: c8 00 00 00 lf.add.s r0,r0,r0 |
assert(*psb++ == 0x78); |
100025a0: 8c 4e 00 03 l.lbz r2,3(r14) |
100025a4: bc 02 00 78 l.sfeqi r2,120 |
100025a8: 10 00 00 0e l.bf 100025e0 <test+0x8f4> |
100025ac: 18 40 10 00 l.movhi r2,0x1000 |
100025b0: 18 60 10 00 l.movhi r3,0x1000 |
100025b4: a8 42 2f 51 l.ori r2,r2,0x2f51 |
100025b8: a8 63 2c 74 l.ori r3,r3,0x2c74 |
100025bc: d4 01 10 00 l.sw 0(r1),r2 |
100025c0: 18 40 10 00 l.movhi r2,0x1000 |
100025c4: a8 42 2d 34 l.ori r2,r2,0x2d34 |
100025c8: d4 01 10 04 l.sw 4(r1),r2 |
100025cc: 9c 40 00 7c l.addi r2,r0,124 |
100025d0: d4 01 10 08 l.sw 8(r1),r2 |
100025d4: 07 ff fd 04 l.jal 100019e4 <printf> |
|
} |
|
static inline void exit(unsigned exit_code) |
{ |
volatile register char t1 asm ("r1") = exit_code; |
100025d8: 9c 20 00 01 l.addi r1,r0,1 |
__asm__ __volatile__ ( "\t l.trap 0 "); |
} |
else |
{ |
// Invalid instruction! |
__asm__ __volatile__ ( "\t lf.add.s r0,r0,r0 "); |
100025dc: c8 00 00 00 lf.add.s r0,r0,r0 |
psb = &uvar; |
*psb++ = 0xab; |
100025e0: 9c 80 ff ab l.addi r4,r0,-85 |
assert(uvar == 0xab345678); |
100025e4: 18 60 ab 34 l.movhi r3,0xab34 |
assert(*psb++ == 0x12); |
assert(*psb++ == 0x34); |
assert(*psb++ == 0x56); |
assert(*psb++ == 0x78); |
psb = &uvar; |
*psb++ = 0xab; |
100025e8: d8 0e 20 00 l.sb 0(r14),r4 |
assert(uvar == 0xab345678); |
100025ec: a8 63 56 78 l.ori r3,r3,0x5678 |
100025f0: 84 4e 00 00 l.lwz r2,0(r14) |
100025f4: e4 02 18 00 l.sfeq r2,r3 |
100025f8: 10 00 00 0e l.bf 10002630 <test+0x944> |
100025fc: 18 40 10 00 l.movhi r2,0x1000 |
10002600: 18 60 10 00 l.movhi r3,0x1000 |
10002604: a8 42 2f 60 l.ori r2,r2,0x2f60 |
10002608: a8 63 2c 74 l.ori r3,r3,0x2c74 |
1000260c: d4 01 10 00 l.sw 0(r1),r2 |
10002610: 18 40 10 00 l.movhi r2,0x1000 |
10002614: a8 42 2d 34 l.ori r2,r2,0x2d34 |
10002618: d4 01 10 04 l.sw 4(r1),r2 |
1000261c: 9c 40 00 7f l.addi r2,r0,127 |
10002620: d4 01 10 08 l.sw 8(r1),r2 |
10002624: 07 ff fc f0 l.jal 100019e4 <printf> |
|
} |
|
static inline void exit(unsigned exit_code) |
{ |
volatile register char t1 asm ("r1") = exit_code; |
10002628: 9c 20 00 01 l.addi r1,r0,1 |
__asm__ __volatile__ ( "\t l.trap 0 "); |
} |
else |
{ |
// Invalid instruction! |
__asm__ __volatile__ ( "\t lf.add.s r0,r0,r0 "); |
1000262c: c8 00 00 00 lf.add.s r0,r0,r0 |
*psb++ = 0xcd; |
10002630: 9c 80 ff cd l.addi r4,r0,-51 |
assert(uvar == 0xabcd5678); |
10002634: 18 60 ab cd l.movhi r3,0xabcd |
assert(*psb++ == 0x56); |
assert(*psb++ == 0x78); |
psb = &uvar; |
*psb++ = 0xab; |
assert(uvar == 0xab345678); |
*psb++ = 0xcd; |
10002638: d8 0e 20 01 l.sb 1(r14),r4 |
assert(uvar == 0xabcd5678); |
1000263c: a8 63 56 78 l.ori r3,r3,0x5678 |
10002640: 84 4e 00 00 l.lwz r2,0(r14) |
10002644: e4 02 18 00 l.sfeq r2,r3 |
10002648: 10 00 00 0e l.bf 10002680 <test+0x994> |
1000264c: 18 40 10 00 l.movhi r2,0x1000 |
10002650: 18 60 10 00 l.movhi r3,0x1000 |
10002654: a8 42 2f 73 l.ori r2,r2,0x2f73 |
10002658: a8 63 2c 74 l.ori r3,r3,0x2c74 |
1000265c: d4 01 10 00 l.sw 0(r1),r2 |
10002660: 18 40 10 00 l.movhi r2,0x1000 |
10002664: a8 42 2d 34 l.ori r2,r2,0x2d34 |
10002668: d4 01 10 04 l.sw 4(r1),r2 |
1000266c: 9c 40 00 81 l.addi r2,r0,129 |
10002670: d4 01 10 08 l.sw 8(r1),r2 |
10002674: 07 ff fc dc l.jal 100019e4 <printf> |
|
} |
|
static inline void exit(unsigned exit_code) |
{ |
volatile register char t1 asm ("r1") = exit_code; |
10002678: 9c 20 00 01 l.addi r1,r0,1 |
__asm__ __volatile__ ( "\t l.trap 0 "); |
} |
else |
{ |
// Invalid instruction! |
__asm__ __volatile__ ( "\t lf.add.s r0,r0,r0 "); |
1000267c: c8 00 00 00 lf.add.s r0,r0,r0 |
*psb++ = 0xef; |
10002680: 9c 80 ff ef l.addi r4,r0,-17 |
assert(uvar == 0xabcdef78); |
10002684: 18 60 ab cd l.movhi r3,0xabcd |
psb = &uvar; |
*psb++ = 0xab; |
assert(uvar == 0xab345678); |
*psb++ = 0xcd; |
assert(uvar == 0xabcd5678); |
*psb++ = 0xef; |
10002688: d8 0e 20 02 l.sb 2(r14),r4 |
assert(uvar == 0xabcdef78); |
1000268c: a8 63 ef 78 l.ori r3,r3,0xef78 |
10002690: 84 4e 00 00 l.lwz r2,0(r14) |
10002694: e4 02 18 00 l.sfeq r2,r3 |
10002698: 10 00 00 0e l.bf 100026d0 <test+0x9e4> |
1000269c: 18 40 10 00 l.movhi r2,0x1000 |
100026a0: 18 60 10 00 l.movhi r3,0x1000 |
100026a4: a8 42 2f 86 l.ori r2,r2,0x2f86 |
100026a8: a8 63 2c 74 l.ori r3,r3,0x2c74 |
100026ac: d4 01 10 00 l.sw 0(r1),r2 |
100026b0: 18 40 10 00 l.movhi r2,0x1000 |
100026b4: a8 42 2d 34 l.ori r2,r2,0x2d34 |
100026b8: d4 01 10 04 l.sw 4(r1),r2 |
100026bc: 9c 40 00 83 l.addi r2,r0,131 |
100026c0: d4 01 10 08 l.sw 8(r1),r2 |
100026c4: 07 ff fc c8 l.jal 100019e4 <printf> |
|
} |
|
static inline void exit(unsigned exit_code) |
{ |
volatile register char t1 asm ("r1") = exit_code; |
100026c8: 9c 20 00 01 l.addi r1,r0,1 |
__asm__ __volatile__ ( "\t l.trap 0 "); |
} |
else |
{ |
// Invalid instruction! |
__asm__ __volatile__ ( "\t lf.add.s r0,r0,r0 "); |
100026cc: c8 00 00 00 lf.add.s r0,r0,r0 |
*psb++ = 0x01; |
100026d0: 9c 80 00 01 l.addi r4,r0,1 |
assert(uvar == 0xabcdef01); |
100026d4: 18 60 ab cd l.movhi r3,0xabcd |
assert(uvar == 0xab345678); |
*psb++ = 0xcd; |
assert(uvar == 0xabcd5678); |
*psb++ = 0xef; |
assert(uvar == 0xabcdef78); |
*psb++ = 0x01; |
100026d8: d8 0e 20 03 l.sb 3(r14),r4 |
assert(uvar == 0xabcdef01); |
100026dc: a8 63 ef 01 l.ori r3,r3,0xef01 |
100026e0: 84 4e 00 00 l.lwz r2,0(r14) |
100026e4: e4 02 18 00 l.sfeq r2,r3 |
100026e8: 10 00 00 0e l.bf 10002720 <test+0xa34> |
100026ec: 18 40 10 00 l.movhi r2,0x1000 |
100026f0: 18 60 10 00 l.movhi r3,0x1000 |
100026f4: a8 42 2f 99 l.ori r2,r2,0x2f99 |
100026f8: a8 63 2c 74 l.ori r3,r3,0x2c74 |
100026fc: d4 01 10 00 l.sw 0(r1),r2 |
10002700: 18 40 10 00 l.movhi r2,0x1000 |
10002704: a8 42 2d 34 l.ori r2,r2,0x2d34 |
10002708: d4 01 10 04 l.sw 4(r1),r2 |
1000270c: 9c 40 00 85 l.addi r2,r0,133 |
10002710: d4 01 10 08 l.sw 8(r1),r2 |
10002714: 07 ff fc b4 l.jal 100019e4 <printf> |
|
} |
|
static inline void exit(unsigned exit_code) |
{ |
volatile register char t1 asm ("r1") = exit_code; |
10002718: 9c 20 00 01 l.addi r1,r0,1 |
__asm__ __volatile__ ( "\t l.trap 0 "); |
} |
else |
{ |
// Invalid instruction! |
__asm__ __volatile__ ( "\t lf.add.s r0,r0,r0 "); |
1000271c: c8 00 00 00 lf.add.s r0,r0,r0 |
|
serial_putstr("10. Comparision\n"); |
10002720: 18 60 10 00 l.movhi r3,0x1000 |
longvar = 0x1db9; |
10002724: 18 40 10 00 l.movhi r2,0x1000 |
*psb++ = 0xef; |
assert(uvar == 0xabcdef78); |
*psb++ = 0x01; |
assert(uvar == 0xabcdef01); |
|
serial_putstr("10. Comparision\n"); |
10002728: a8 63 2f ac l.ori r3,r3,0x2fac |
longvar = 0x1db9; |
1000272c: a8 42 30 00 l.ori r2,r2,0x3000 |
*psb++ = 0xef; |
assert(uvar == 0xabcdef78); |
*psb++ = 0x01; |
assert(uvar == 0xabcdef01); |
|
serial_putstr("10. Comparision\n"); |
10002730: 07 ff fc fb l.jal 10001b1c <serial_putstr> |
longvar = 0x1db9; |
10002734: 9c 60 1d b9 l.addi r3,r0,7609 |
if (longvar >= 0xFFF8 && longvar <= 0xFFFF) |
10002738: a8 80 ff f7 l.ori r4,r0,0xfff7 |
assert(uvar == 0xabcdef78); |
*psb++ = 0x01; |
assert(uvar == 0xabcdef01); |
|
serial_putstr("10. Comparision\n"); |
longvar = 0x1db9; |
1000273c: d4 02 18 00 l.sw 0(r2),r3 |
if (longvar >= 0xFFF8 && longvar <= 0xFFFF) |
10002740: 84 62 00 00 l.lwz r3,0(r2) |
10002744: e4 a3 20 00 l.sfleu r3,r4 |
10002748: 10 00 00 05 l.bf 1000275c <test+0xa70> |
1000274c: a8 60 ff ff l.ori r3,r0,0xffff |
10002750: 84 42 00 00 l.lwz r2,0(r2) |
10002754: e4 42 18 00 l.sfgtu r2,r3 |
10002758: 0c 00 00 0b l.bnf 10002784 <test+0xa98> |
|
} |
|
static inline void exit(unsigned exit_code) |
{ |
volatile register char t1 asm ("r1") = exit_code; |
1000275c: 9c 20 00 00 l.addi r1,r0,0 |
|
// No error? |
if (exit_code == 0) |
{ |
// Trap instruction |
__asm__ __volatile__ ( "\t l.trap 0 "); |
10002760: 21 00 00 00 l.trap 0x0 |
assert(0); |
} |
|
// Success |
exit(0); |
} |
10002764: 9c 21 00 20 l.addi r1,r1,32 |
10002768: 9d 60 00 00 l.addi r11,r0,0 |
1000276c: 85 21 ff fc l.lwz r9,-4(r1) |
10002770: 84 21 ff ec l.lwz r1,-20(r1) |
10002774: 84 41 ff f0 l.lwz r2,-16(r1) |
10002778: 85 c1 ff f4 l.lwz r14,-12(r1) |
1000277c: 86 41 ff f8 l.lwz r18,-8(r1) |
10002780: 44 00 48 00 l.jr r9 |
|
serial_putstr("10. Comparision\n"); |
longvar = 0x1db9; |
if (longvar >= 0xFFF8 && longvar <= 0xFFFF) |
{ |
serial_putstr("- Incorrect comparision\n"); |
10002784: 18 60 10 00 l.movhi r3,0x1000 |
assert(0); |
10002788: 18 40 10 00 l.movhi r2,0x1000 |
|
serial_putstr("10. Comparision\n"); |
longvar = 0x1db9; |
if (longvar >= 0xFFF8 && longvar <= 0xFFFF) |
{ |
serial_putstr("- Incorrect comparision\n"); |
1000278c: a8 63 2f bd l.ori r3,r3,0x2fbd |
assert(0); |
10002790: a8 42 2d 07 l.ori r2,r2,0x2d07 |
|
serial_putstr("10. Comparision\n"); |
longvar = 0x1db9; |
if (longvar >= 0xFFF8 && longvar <= 0xFFFF) |
{ |
serial_putstr("- Incorrect comparision\n"); |
10002794: 07 ff fc e2 l.jal 10001b1c <serial_putstr> |
assert(0); |
10002798: d4 01 10 00 l.sw 0(r1),r2 |
1000279c: 18 40 10 00 l.movhi r2,0x1000 |
100027a0: 18 60 10 00 l.movhi r3,0x1000 |
100027a4: a8 42 2d 34 l.ori r2,r2,0x2d34 |
100027a8: a8 63 2c 74 l.ori r3,r3,0x2c74 |
100027ac: d4 01 10 04 l.sw 4(r1),r2 |
100027b0: 9c 40 00 8c l.addi r2,r0,140 |
100027b4: d4 01 10 08 l.sw 8(r1),r2 |
100027b8: 07 ff fc 8b l.jal 100019e4 <printf> |
|
} |
|
static inline void exit(unsigned exit_code) |
{ |
volatile register char t1 asm ("r1") = exit_code; |
100027bc: 9c 20 00 01 l.addi r1,r0,1 |
__asm__ __volatile__ ( "\t l.trap 0 "); |
} |
else |
{ |
// Invalid instruction! |
__asm__ __volatile__ ( "\t lf.add.s r0,r0,r0 "); |
100027c0: c8 00 00 00 lf.add.s r0,r0,r0 |
100027c4: 03 ff ff e6 l.j 1000275c <test+0xa70> |
assert(sw == 0x5678); |
psw = &uvar; |
assert(*psw++ == 0x1234); |
assert(*psw++ == 0x5678); |
psw = &uvar; |
*psw = 0xcafe; |
100027c8: 18 40 10 00 l.movhi r2,0x1000 |
100027cc: 9c 80 ca fe l.addi r4,r0,-13570 |
100027d0: a8 42 30 04 l.ori r2,r2,0x3004 |
100027d4: dc 02 20 00 l.sh 0(r2),r4 |
assert(*psw++ == 0xcafe); |
assert(*psw++ == 0x5678); |
psw = &uvar; |
*(++psw) = 0xbabe; |
100027d8: 9c 40 ba be l.addi r2,r0,-17730 |
100027dc: dc 0e 10 02 l.sh 2(r14),r2 |
100027e0: 03 ff ff 17 l.j 1000243c <test+0x750> |
x = 10; |
assert(var < x); |
assert(!(var > x)); |
x = -3; |
assert(var > x); |
assert(x <= var); |
100027e4: 18 40 10 00 l.movhi r2,0x1000 |
100027e8: 18 60 10 00 l.movhi r3,0x1000 |
100027ec: a8 42 2e 8c l.ori r2,r2,0x2e8c |
100027f0: a8 63 2c 74 l.ori r3,r3,0x2c74 |
100027f4: d4 01 10 00 l.sw 0(r1),r2 |
100027f8: 18 40 10 00 l.movhi r2,0x1000 |
100027fc: a8 42 2d 34 l.ori r2,r2,0x2d34 |
10002800: d4 01 10 04 l.sw 4(r1),r2 |
10002804: 9c 40 00 5f l.addi r2,r0,95 |
10002808: d4 01 10 08 l.sw 8(r1),r2 |
1000280c: 07 ff fc 76 l.jal 100019e4 <printf> |
|
} |
|
static inline void exit(unsigned exit_code) |
{ |
volatile register char t1 asm ("r1") = exit_code; |
10002810: 9c 20 00 01 l.addi r1,r0,1 |
__asm__ __volatile__ ( "\t l.trap 0 "); |
} |
else |
{ |
// Invalid instruction! |
__asm__ __volatile__ ( "\t lf.add.s r0,r0,r0 "); |
10002814: c8 00 00 00 lf.add.s r0,r0,r0 |
10002818: 03 ff fe 92 l.j 10002260 <test+0x574> |
assert(var < 1); |
x = 10; |
assert(var < x); |
assert(!(var > x)); |
x = -3; |
assert(var > x); |
1000281c: 18 60 10 00 l.movhi r3,0x1000 |
10002820: a8 63 2e 84 l.ori r3,r3,0x2e84 |
10002824: d4 01 18 00 l.sw 0(r1),r3 |
10002828: 18 60 10 00 l.movhi r3,0x1000 |
1000282c: a8 63 2d 34 l.ori r3,r3,0x2d34 |
10002830: d4 01 18 04 l.sw 4(r1),r3 |
10002834: 9c 60 00 5e l.addi r3,r0,94 |
10002838: d4 01 18 08 l.sw 8(r1),r3 |
1000283c: 18 60 10 00 l.movhi r3,0x1000 |
10002840: a8 63 2c 74 l.ori r3,r3,0x2c74 |
10002844: 07 ff fc 68 l.jal 100019e4 <printf> |
|
} |
|
static inline void exit(unsigned exit_code) |
{ |
volatile register char t1 asm ("r1") = exit_code; |
10002848: 9c 20 00 01 l.addi r1,r0,1 |
__asm__ __volatile__ ( "\t l.trap 0 "); |
} |
else |
{ |
// Invalid instruction! |
__asm__ __volatile__ ( "\t lf.add.s r0,r0,r0 "); |
1000284c: c8 00 00 00 lf.add.s r0,r0,r0 |
10002850: 03 ff fe 81 l.j 10002254 <test+0x568> |
serial_putstr("7. Signed comparision\n"); |
var = -1; |
assert(var < 1); |
x = 10; |
assert(var < x); |
assert(!(var > x)); |
10002854: 18 60 10 00 l.movhi r3,0x1000 |
10002858: a8 63 2e 79 l.ori r3,r3,0x2e79 |
1000285c: d4 01 18 00 l.sw 0(r1),r3 |
10002860: 18 60 10 00 l.movhi r3,0x1000 |
10002864: a8 63 2d 34 l.ori r3,r3,0x2d34 |
10002868: d4 01 18 04 l.sw 4(r1),r3 |
1000286c: 9c 60 00 5c l.addi r3,r0,92 |
10002870: d4 01 18 08 l.sw 8(r1),r3 |
10002874: 18 60 10 00 l.movhi r3,0x1000 |
10002878: a8 63 2c 74 l.ori r3,r3,0x2c74 |
1000287c: 07 ff fc 5a l.jal 100019e4 <printf> |
|
} |
|
static inline void exit(unsigned exit_code) |
{ |
volatile register char t1 asm ("r1") = exit_code; |
10002880: 9c 20 00 01 l.addi r1,r0,1 |
__asm__ __volatile__ ( "\t l.trap 0 "); |
} |
else |
{ |
// Invalid instruction! |
__asm__ __volatile__ ( "\t lf.add.s r0,r0,r0 "); |
10002884: c8 00 00 00 lf.add.s r0,r0,r0 |
10002888: 03 ff fe 70 l.j 10002248 <test+0x55c> |
|
serial_putstr("7. Signed comparision\n"); |
var = -1; |
assert(var < 1); |
x = 10; |
assert(var < x); |
1000288c: 18 60 10 00 l.movhi r3,0x1000 |
10002890: a8 63 2e 71 l.ori r3,r3,0x2e71 |
10002894: d4 01 18 00 l.sw 0(r1),r3 |
10002898: 18 60 10 00 l.movhi r3,0x1000 |
1000289c: a8 63 2d 34 l.ori r3,r3,0x2d34 |
100028a0: d4 01 18 04 l.sw 4(r1),r3 |
100028a4: 9c 60 00 5b l.addi r3,r0,91 |
100028a8: d4 01 18 08 l.sw 8(r1),r3 |
100028ac: 18 60 10 00 l.movhi r3,0x1000 |
100028b0: a8 63 2c 74 l.ori r3,r3,0x2c74 |
100028b4: 07 ff fc 4c l.jal 100019e4 <printf> |
|
} |
|
static inline void exit(unsigned exit_code) |
{ |
volatile register char t1 asm ("r1") = exit_code; |
100028b8: 9c 20 00 01 l.addi r1,r0,1 |
__asm__ __volatile__ ( "\t l.trap 0 "); |
} |
else |
{ |
// Invalid instruction! |
__asm__ __volatile__ ( "\t lf.add.s r0,r0,r0 "); |
100028bc: c8 00 00 00 lf.add.s r0,r0,r0 |
100028c0: 03 ff fe 5f l.j 1000223c <test+0x550> |
// Assign empty syscall handler |
exception_register_syscall_handler(empty_syscall); |
|
serial_putstr("1. Initialised data\n"); |
assert(var == 0x1234); // .text |
assert(uvar == 0x0); // .bss |
100028c4: 18 60 10 00 l.movhi r3,0x1000 |
100028c8: a8 63 2d 3b l.ori r3,r3,0x2d3b |
100028cc: d4 01 18 00 l.sw 0(r1),r3 |
100028d0: 18 60 10 00 l.movhi r3,0x1000 |
100028d4: a8 63 2d 34 l.ori r3,r3,0x2d34 |
100028d8: d4 01 18 04 l.sw 4(r1),r3 |
100028dc: 9c 60 00 2a l.addi r3,r0,42 |
100028e0: d4 01 18 08 l.sw 8(r1),r3 |
100028e4: 18 60 10 00 l.movhi r3,0x1000 |
100028e8: a8 63 2c 74 l.ori r3,r3,0x2c74 |
100028ec: 07 ff fc 3e l.jal 100019e4 <printf> |
|
} |
|
static inline void exit(unsigned exit_code) |
{ |
volatile register char t1 asm ("r1") = exit_code; |
100028f0: 9c 20 00 01 l.addi r1,r0,1 |
__asm__ __volatile__ ( "\t l.trap 0 "); |
} |
else |
{ |
// Invalid instruction! |
__asm__ __volatile__ ( "\t lf.add.s r0,r0,r0 "); |
100028f4: c8 00 00 00 lf.add.s r0,r0,r0 |
100028f8: 03 ff fd 23 l.j 10001d84 <test+0x98> |
|
100028fc <__udivsi3>: |
|
long udivmodsi4 (); |
|
long |
__udivsi3 (long a, long b) |
{ |
100028fc: d7 e1 4f fc l.sw -4(r1),r9 |
10002900: d7 e1 0f f8 l.sw -8(r1),r1 |
return udivmodsi4 (a, b, 0); |
10002904: 9c a0 00 00 l.addi r5,r0,0 |
|
long udivmodsi4 (); |
|
long |
__udivsi3 (long a, long b) |
{ |
10002908: 9c 21 ff f8 l.addi r1,r1,-8 |
return udivmodsi4 (a, b, 0); |
1000290c: 04 00 00 40 l.jal 10002a0c <udivmodsi4> |
} |
10002910: 9c 21 00 08 l.addi r1,r1,8 |
10002914: 85 21 ff fc l.lwz r9,-4(r1) |
10002918: 84 21 ff f8 l.lwz r1,-8(r1) |
1000291c: 44 00 48 00 l.jr r9 |
|
10002920 <__umodsi3>: |
|
long |
__umodsi3 (long a, long b) |
{ |
10002920: d7 e1 4f fc l.sw -4(r1),r9 |
10002924: d7 e1 0f f8 l.sw -8(r1),r1 |
return udivmodsi4 (a, b, 1); |
10002928: 9c a0 00 01 l.addi r5,r0,1 |
return udivmodsi4 (a, b, 0); |
} |
|
long |
__umodsi3 (long a, long b) |
{ |
1000292c: 9c 21 ff f8 l.addi r1,r1,-8 |
return udivmodsi4 (a, b, 1); |
10002930: 04 00 00 37 l.jal 10002a0c <udivmodsi4> |
} |
10002934: 9c 21 00 08 l.addi r1,r1,8 |
10002938: 85 21 ff fc l.lwz r9,-4(r1) |
1000293c: 84 21 ff f8 l.lwz r1,-8(r1) |
10002940: 44 00 48 00 l.jr r9 |
|
10002944 <__divsi3>: |
|
long udivmodsi4 (); |
|
long |
__divsi3 (long a, long b) |
{ |
10002944: d7 e1 17 f8 l.sw -8(r1),r2 |
10002948: d7 e1 4f fc l.sw -4(r1),r9 |
1000294c: d7 e1 0f f4 l.sw -12(r1),r1 |
int neg = 0; |
long res; |
|
if (a < 0) |
10002950: bd 63 00 00 l.sfgesi r3,0 |
|
long udivmodsi4 (); |
|
long |
__divsi3 (long a, long b) |
{ |
10002954: 9c 21 ff f4 l.addi r1,r1,-12 |
int neg = 0; |
10002958: 9c 40 00 00 l.addi r2,r0,0 |
long res; |
|
if (a < 0) |
1000295c: 0c 00 00 0d l.bnf 10002990 <__divsi3+0x4c> |
{ |
a = -a; |
neg = !neg; |
} |
|
if (b < 0) |
10002960: bd 64 00 00 l.sfgesi r4,0 |
10002964: 0c 00 00 0f l.bnf 100029a0 <__divsi3+0x5c> |
{ |
b = -b; |
neg = !neg; |
} |
|
res = udivmodsi4 (a, b, 0); |
10002968: 9c a0 00 00 l.addi r5,r0,0 |
1000296c: 04 00 00 28 l.jal 10002a0c <udivmodsi4> |
|
if (neg) |
10002970: bc 02 00 00 l.sfeqi r2,0 |
10002974: 10 00 00 02 l.bf 1000297c <__divsi3+0x38> |
res = -res; |
10002978: e1 60 58 02 l.sub r11,r0,r11 |
|
return res; |
} |
1000297c: 9c 21 00 0c l.addi r1,r1,12 |
10002980: 85 21 ff fc l.lwz r9,-4(r1) |
10002984: 84 21 ff f4 l.lwz r1,-12(r1) |
10002988: 84 41 ff f8 l.lwz r2,-8(r1) |
1000298c: 44 00 48 00 l.jr r9 |
{ |
a = -a; |
neg = !neg; |
} |
|
if (b < 0) |
10002990: bd 64 00 00 l.sfgesi r4,0 |
int neg = 0; |
long res; |
|
if (a < 0) |
{ |
a = -a; |
10002994: e0 60 18 02 l.sub r3,r0,r3 |
neg = !neg; |
10002998: 9c 40 00 01 l.addi r2,r0,1 |
} |
|
if (b < 0) |
1000299c: 13 ff ff f3 l.bf 10002968 <__divsi3+0x24> |
{ |
b = -b; |
100029a0: e0 80 20 02 l.sub r4,r0,r4 |
100029a4: ac 42 00 01 l.xori r2,r2,1 |
100029a8: 03 ff ff f0 l.j 10002968 <__divsi3+0x24> |
|
100029ac <__modsi3>: |
return res; |
} |
|
long |
__modsi3 (long a, long b) |
{ |
100029ac: d7 e1 4f fc l.sw -4(r1),r9 |
100029b0: d7 e1 0f f8 l.sw -8(r1),r1 |
int neg = 0; |
long res; |
|
if (a < 0) |
100029b4: bd 63 00 00 l.sfgesi r3,0 |
return res; |
} |
|
long |
__modsi3 (long a, long b) |
{ |
100029b8: 9c 21 ff f8 l.addi r1,r1,-8 |
100029bc: b8 c4 00 9f l.srai r6,r4,0x1f |
int neg = 0; |
long res; |
|
if (a < 0) |
100029c0: 0c 00 00 09 l.bnf 100029e4 <__modsi3+0x38> |
100029c4: e0 86 20 05 l.xor r4,r6,r4 |
} |
|
if (b < 0) |
b = -b; |
|
res = udivmodsi4 (a, b, 1); |
100029c8: 9c a0 00 01 l.addi r5,r0,1 |
100029cc: e0 84 30 02 l.sub r4,r4,r6 |
100029d0: 04 00 00 0f l.jal 10002a0c <udivmodsi4> |
|
if (neg) |
res = -res; |
|
return res; |
} |
100029d4: 9c 21 00 08 l.addi r1,r1,8 |
100029d8: 85 21 ff fc l.lwz r9,-4(r1) |
100029dc: 84 21 ff f8 l.lwz r1,-8(r1) |
100029e0: 44 00 48 00 l.jr r9 |
100029e4: e0 86 20 05 l.xor r4,r6,r4 |
} |
|
if (b < 0) |
b = -b; |
|
res = udivmodsi4 (a, b, 1); |
100029e8: e0 60 18 02 l.sub r3,r0,r3 |
100029ec: 9c a0 00 01 l.addi r5,r0,1 |
100029f0: e0 84 30 02 l.sub r4,r4,r6 |
100029f4: 04 00 00 06 l.jal 10002a0c <udivmodsi4> |
|
if (neg) |
res = -res; |
|
return res; |
} |
100029f8: 9c 21 00 08 l.addi r1,r1,8 |
b = -b; |
|
res = udivmodsi4 (a, b, 1); |
|
if (neg) |
res = -res; |
100029fc: e1 60 58 02 l.sub r11,r0,r11 |
|
return res; |
} |
10002a00: 85 21 ff fc l.lwz r9,-4(r1) |
10002a04: 84 21 ff f8 l.lwz r1,-8(r1) |
10002a08: 44 00 48 00 l.jr r9 |
|
10002a0c <udivmodsi4>: |
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
<http://www.gnu.org/licenses/>. */ |
|
unsigned long |
udivmodsi4(unsigned long num, unsigned long den, int modwanted) |
{ |
10002a0c: d7 e1 0f fc l.sw -4(r1),r1 |
unsigned long bit = 1; |
unsigned long res = 0; |
|
while (den < num && bit && !(den & (1L<<31))) |
10002a10: e4 64 18 00 l.sfgeu r4,r3 |
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
<http://www.gnu.org/licenses/>. */ |
|
unsigned long |
udivmodsi4(unsigned long num, unsigned long den, int modwanted) |
{ |
10002a14: 9c 21 ff fc l.addi r1,r1,-4 |
unsigned long bit = 1; |
unsigned long res = 0; |
|
while (den < num && bit && !(den & (1L<<31))) |
10002a18: 10 00 00 26 l.bf 10002ab0 <udivmodsi4+0xa4> |
10002a1c: bd 64 00 00 l.sfgesi r4,0 |
<http://www.gnu.org/licenses/>. */ |
|
unsigned long |
udivmodsi4(unsigned long num, unsigned long den, int modwanted) |
{ |
unsigned long bit = 1; |
10002a20: 9c c0 00 01 l.addi r6,r0,1 |
unsigned long res = 0; |
|
while (den < num && bit && !(den & (1L<<31))) |
10002a24: 10 00 00 06 l.bf 10002a3c <udivmodsi4+0x30> |
10002a28: 00 00 00 13 l.j 10002a74 <udivmodsi4+0x68> |
10002a2c: bd 88 00 00 l.sfltsi r8,0 |
10002a30: 0c 00 00 0e l.bnf 10002a68 <udivmodsi4+0x5c> |
10002a34: bd 84 00 00 l.sfltsi r4,0 |
10002a38: 10 00 00 0f l.bf 10002a74 <udivmodsi4+0x68> |
{ |
den <<=1; |
bit <<=1; |
10002a3c: e0 c6 30 00 l.add r6,r6,r6 |
unsigned long bit = 1; |
unsigned long res = 0; |
|
while (den < num && bit && !(den & (1L<<31))) |
{ |
den <<=1; |
10002a40: e0 84 20 00 l.add r4,r4,r4 |
udivmodsi4(unsigned long num, unsigned long den, int modwanted) |
{ |
unsigned long bit = 1; |
unsigned long res = 0; |
|
while (den < num && bit && !(den & (1L<<31))) |
10002a44: e1 00 30 02 l.sub r8,r0,r6 |
10002a48: e4 43 20 00 l.sfgtu r3,r4 |
10002a4c: 9c e0 00 01 l.addi r7,r0,1 |
10002a50: e1 08 30 04 l.or r8,r8,r6 |
10002a54: 10 00 00 02 l.bf 10002a5c <udivmodsi4+0x50> |
10002a58: 9c e0 00 00 l.addi r7,r0,0 |
10002a5c: a4 e7 00 ff l.andi r7,r7,0xff |
10002a60: bc 07 00 00 l.sfeqi r7,0 |
10002a64: 0f ff ff f2 l.bnf 10002a2c <udivmodsi4+0x20> |
{ |
den <<=1; |
bit <<=1; |
} |
while (bit) |
10002a68: bc 26 00 00 l.sfnei r6,0 |
10002a6c: a9 66 00 00 l.ori r11,r6,0x0 |
10002a70: 0c 00 00 0a l.bnf 10002a98 <udivmodsi4+0x8c> |
unsigned long res = 0; |
|
while (den < num && bit && !(den & (1L<<31))) |
{ |
den <<=1; |
bit <<=1; |
10002a74: 9d 60 00 00 l.addi r11,r0,0 |
} |
while (bit) |
{ |
if (num >= den) |
10002a78: e4 83 20 00 l.sfltu r3,r4 |
10002a7c: 10 00 00 03 l.bf 10002a88 <udivmodsi4+0x7c> |
{ |
num -= den; |
10002a80: e0 63 20 02 l.sub r3,r3,r4 |
res |= bit; |
10002a84: e1 6b 30 04 l.or r11,r11,r6 |
} |
bit >>=1; |
10002a88: b8 c6 00 41 l.srli r6,r6,0x1 |
den >>=1; |
10002a8c: b8 84 00 41 l.srli r4,r4,0x1 |
while (den < num && bit && !(den & (1L<<31))) |
{ |
den <<=1; |
bit <<=1; |
} |
while (bit) |
10002a90: bc 06 00 00 l.sfeqi r6,0 |
10002a94: 0f ff ff f9 l.bnf 10002a78 <udivmodsi4+0x6c> |
res |= bit; |
} |
bit >>=1; |
den >>=1; |
} |
if (modwanted) return num; |
10002a98: bc 05 00 00 l.sfeqi r5,0 |
10002a9c: 10 00 00 02 l.bf 10002aa4 <udivmodsi4+0x98> |
10002aa0: a9 63 00 00 l.ori r11,r3,0x0 |
return res; |
} |
10002aa4: 9c 21 00 04 l.addi r1,r1,4 |
10002aa8: 84 21 ff fc l.lwz r1,-4(r1) |
10002aac: 44 00 48 00 l.jr r9 |
udivmodsi4(unsigned long num, unsigned long den, int modwanted) |
{ |
unsigned long bit = 1; |
unsigned long res = 0; |
|
while (den < num && bit && !(den & (1L<<31))) |
10002ab0: 9c c0 00 01 l.addi r6,r0,1 |
10002ab4: 03 ff ff f0 l.j 10002a74 <udivmodsi4+0x68> |
|
10002ab8 <__mulsi3>: |
|
typedef unsigned int USItype __attribute__ ((mode (SI))); |
|
USItype |
__mulsi3 (USItype a, USItype b) |
{ |
10002ab8: d7 e1 0f fc l.sw -4(r1),r1 |
USItype c = 0; |
|
while (a != 0) |
10002abc: bc 03 00 00 l.sfeqi r3,0 |
|
typedef unsigned int USItype __attribute__ ((mode (SI))); |
|
USItype |
__mulsi3 (USItype a, USItype b) |
{ |
10002ac0: 9c 21 ff fc l.addi r1,r1,-4 |
USItype c = 0; |
|
while (a != 0) |
10002ac4: 10 00 00 0d l.bf 10002af8 <__mulsi3+0x40> |
typedef unsigned int USItype __attribute__ ((mode (SI))); |
|
USItype |
__mulsi3 (USItype a, USItype b) |
{ |
USItype c = 0; |
10002ac8: 9d 60 00 00 l.addi r11,r0,0 |
|
while (a != 0) |
{ |
if (a & 1) |
10002acc: a4 a3 00 01 l.andi r5,r3,0x1 |
10002ad0: b8 63 00 41 l.srli r3,r3,0x1 |
10002ad4: bc 05 00 00 l.sfeqi r5,0 |
10002ad8: 10 00 00 02 l.bf 10002ae0 <__mulsi3+0x28> |
c += b; |
10002adc: e1 6b 20 00 l.add r11,r11,r4 |
USItype |
__mulsi3 (USItype a, USItype b) |
{ |
USItype c = 0; |
|
while (a != 0) |
10002ae0: bc 03 00 00 l.sfeqi r3,0 |
{ |
if (a & 1) |
c += b; |
a >>= 1; |
b <<= 1; |
10002ae4: e0 84 20 00 l.add r4,r4,r4 |
USItype |
__mulsi3 (USItype a, USItype b) |
{ |
USItype c = 0; |
|
while (a != 0) |
10002ae8: 0f ff ff f9 l.bnf 10002acc <__mulsi3+0x14> |
a >>= 1; |
b <<= 1; |
} |
|
return c; |
} |
10002aec: 9c 21 00 04 l.addi r1,r1,4 |
10002af0: 84 21 ff fc l.lwz r1,-4(r1) |
10002af4: 44 00 48 00 l.jr r9 |
typedef unsigned int USItype __attribute__ ((mode (SI))); |
|
USItype |
__mulsi3 (USItype a, USItype b) |
{ |
USItype c = 0; |
10002af8: a9 63 00 00 l.ori r11,r3,0x0 |
10002afc: 03 ff ff fc l.j 10002aec <__mulsi3+0x34> |
10002b00: 10 00 12 b8 l.bf 100075e0 <_end+0x35d0> |
10002b04: 10 00 11 a0 l.bf 10007184 <_end+0x3174> |
10002b08: 10 00 11 bc l.bf 100071f8 <_end+0x31e8> |
10002b0c: 10 00 11 f0 l.bf 100072cc <_end+0x32bc> |
10002b10: 10 00 12 24 l.bf 100073a0 <_end+0x3390> |
10002b14: 10 00 12 58 l.bf 10007474 <_end+0x3464> |
10002b18: 10 00 12 78 l.bf 100074f8 <_end+0x34e8> |
10002b1c: 10 00 12 98 l.bf 1000757c <_end+0x356c> |
10002b20: 10 00 11 10 l.bf 10006f60 <_end+0x2f50> |
10002b24: 10 00 18 dc l.bf 10008e94 <_end+0x4e84> |
10002b28: 10 00 16 2c l.bf 100083d8 <_end+0x43c8> |
10002b2c: 10 00 16 2c l.bf 100083dc <_end+0x43cc> |
10002b30: 10 00 16 2c l.bf 100083e0 <_end+0x43d0> |
10002b34: 10 00 16 2c l.bf 100083e4 <_end+0x43d4> |
10002b38: 10 00 16 2c l.bf 100083e8 <_end+0x43d8> |
10002b3c: 10 00 16 2c l.bf 100083ec <_end+0x43dc> |
10002b40: 10 00 16 2c l.bf 100083f0 <_end+0x43e0> |
10002b44: 10 00 18 c4 l.bf 10008e54 <_end+0x4e44> |
10002b48: 10 00 18 ac l.bf 10008df8 <_end+0x4de8> |
10002b4c: 10 00 16 2c l.bf 100083fc <_end+0x43ec> |
10002b50: 10 00 16 2c l.bf 10008400 <_end+0x43f0> |
10002b54: 10 00 16 2c l.bf 10008404 <_end+0x43f4> |
10002b58: 10 00 16 2c l.bf 10008408 <_end+0x43f8> |
10002b5c: 10 00 16 2c l.bf 1000840c <_end+0x43fc> |
10002b60: 10 00 16 2c l.bf 10008410 <_end+0x4400> |
10002b64: 10 00 16 2c l.bf 10008414 <_end+0x4404> |
10002b68: 10 00 16 2c l.bf 10008418 <_end+0x4408> |
10002b6c: 10 00 16 2c l.bf 1000841c <_end+0x440c> |
10002b70: 10 00 16 2c l.bf 10008420 <_end+0x4410> |
10002b74: 10 00 16 2c l.bf 10008424 <_end+0x4414> |
10002b78: 10 00 16 2c l.bf 10008428 <_end+0x4418> |
10002b7c: 10 00 16 2c l.bf 1000842c <_end+0x441c> |
10002b80: 10 00 16 2c l.bf 10008430 <_end+0x4420> |
10002b84: 10 00 16 2c l.bf 10008434 <_end+0x4424> |
10002b88: 10 00 16 2c l.bf 10008438 <_end+0x4428> |
10002b8c: 10 00 16 2c l.bf 1000843c <_end+0x442c> |
10002b90: 10 00 16 2c l.bf 10008440 <_end+0x4430> |
10002b94: 10 00 16 2c l.bf 10008444 <_end+0x4434> |
10002b98: 10 00 16 2c l.bf 10008448 <_end+0x4438> |
10002b9c: 10 00 16 2c l.bf 1000844c <_end+0x443c> |
10002ba0: 10 00 16 2c l.bf 10008450 <_end+0x4440> |
10002ba4: 10 00 16 2c l.bf 10008454 <_end+0x4444> |
10002ba8: 10 00 16 2c l.bf 10008458 <_end+0x4448> |
10002bac: 10 00 16 2c l.bf 1000845c <_end+0x444c> |
10002bb0: 10 00 16 2c l.bf 10008460 <_end+0x4450> |
10002bb4: 10 00 16 2c l.bf 10008464 <_end+0x4454> |
10002bb8: 10 00 16 2c l.bf 10008468 <_end+0x4458> |
10002bbc: 10 00 16 2c l.bf 1000846c <_end+0x445c> |
10002bc0: 10 00 16 2c l.bf 10008470 <_end+0x4460> |
10002bc4: 10 00 16 2c l.bf 10008474 <_end+0x4464> |
10002bc8: 10 00 16 2c l.bf 10008478 <_end+0x4468> |
10002bcc: 10 00 16 2c l.bf 1000847c <_end+0x446c> |
10002bd0: 10 00 16 2c l.bf 10008480 <_end+0x4470> |
10002bd4: 10 00 16 2c l.bf 10008484 <_end+0x4474> |
10002bd8: 10 00 16 2c l.bf 10008488 <_end+0x4478> |
10002bdc: 10 00 16 2c l.bf 1000848c <_end+0x447c> |
10002be0: 10 00 16 2c l.bf 10008490 <_end+0x4480> |
10002be4: 10 00 16 2c l.bf 10008494 <_end+0x4484> |
10002be8: 10 00 16 2c l.bf 10008498 <_end+0x4488> |
10002bec: 10 00 16 2c l.bf 1000849c <_end+0x448c> |
10002bf0: 10 00 16 2c l.bf 100084a0 <_end+0x4490> |
10002bf4: 10 00 16 2c l.bf 100084a4 <_end+0x4494> |
10002bf8: 10 00 16 2c l.bf 100084a8 <_end+0x4498> |
10002bfc: 10 00 16 2c l.bf 100084ac <_end+0x449c> |
10002c00: 10 00 18 7c l.bf 10008df0 <_end+0x4de0> |
10002c04: 10 00 16 2c l.bf 100084b4 <_end+0x44a4> |
10002c08: 10 00 16 2c l.bf 100084b8 <_end+0x44a8> |
10002c0c: 10 00 16 2c l.bf 100084bc <_end+0x44ac> |
10002c10: 10 00 16 2c l.bf 100084c0 <_end+0x44b0> |
10002c14: 10 00 16 2c l.bf 100084c4 <_end+0x44b4> |
10002c18: 10 00 16 2c l.bf 100084c8 <_end+0x44b8> |
10002c1c: 10 00 18 68 l.bf 10008dbc <_end+0x4dac> |
10002c20: 10 00 18 50 l.bf 10008d60 <_end+0x4d50> |
10002c24: 10 00 16 2c l.bf 100084d4 <_end+0x44c4> |
10002c28: 10 00 16 2c l.bf 100084d8 <_end+0x44c8> |
10002c2c: 10 00 16 2c l.bf 100084dc <_end+0x44cc> |
10002c30: 10 00 16 2c l.bf 100084e0 <_end+0x44d0> |
10002c34: 10 00 16 2c l.bf 100084e4 <_end+0x44d4> |
10002c38: 10 00 16 2c l.bf 100084e8 <_end+0x44d8> |
10002c3c: 10 00 16 2c l.bf 100084ec <_end+0x44dc> |
10002c40: 10 00 18 3c l.bf 10008d30 <_end+0x4d20> |
10002c44: 10 00 16 2c l.bf 100084f4 <_end+0x44e4> |
10002c48: 10 00 16 2c l.bf 100084f8 <_end+0x44e8> |
10002c4c: 10 00 16 2c l.bf 100084fc <_end+0x44ec> |
10002c50: 10 00 18 1c l.bf 10008cc0 <_end+0x4cb0> |
10002c54: 10 00 16 2c l.bf 10008504 <_end+0x44f4> |
10002c58: 10 00 16 2c l.bf 10008508 <_end+0x44f8> |
10002c5c: 10 00 17 34 l.bf 1000892c <_end+0x491c> |
10002c60: 10 00 16 2c l.bf 10008510 <_end+0x4500> |
10002c64: 10 00 16 2c l.bf 10008514 <_end+0x4504> |
10002c68: 10 00 16 2c l.bf 10008518 <_end+0x4508> |
10002c6c: 10 00 16 2c l.bf 1000851c <_end+0x450c> |
10002c70: 10 00 18 1c l.bf 10008ce0 <_end+0x4cd0> |
10002c74: 41 73 73 65 *unknown* |
10002c78: 72 74 20 66 *unknown* |
10002c7c: 61 69 6c 65 *unknown* |
10002c80: 64 3a 20 25 *unknown* |
10002c84: 73 20 28 25 *unknown* |
10002c88: 73 3a 25 64 *unknown* |
10002c8c: 29 0a 00 22 *unknown* |
10002c90: 53 59 53 43 *unknown* |
10002c94: 41 4c 4c 21 *unknown* |
10002c98: 22 00 2e 2e *unknown* |
10002c9c: 2f 63 6f 6d *unknown* |
10002ca0: 6d 6f 6e 2f *unknown* |
10002ca4: 65 78 63 65 *unknown* |
10002ca8: 70 74 69 6f *unknown* |
10002cac: 6e 2e 63 00 *unknown* |
10002cb0: 22 42 52 45 *unknown* |
10002cb4: 41 4b 21 22 *unknown* |
10002cb8: 00 22 45 58 l.j 10894218 <_end+0x890208> |
10002cbc: 54 5f 49 4e *unknown* |
10002cc0: 54 21 22 00 *unknown* |
10002cc4: 22 46 41 55 *unknown* |
10002cc8: 4c 54 22 00 *unknown* |
10002ccc: 22 4d 55 4c *unknown* |
10002cd0: 54 21 22 00 *unknown* |
10002cd4: 22 55 4d 55 *unknown* |
10002cd8: 4c 54 21 22 *unknown* |
10002cdc: 00 22 44 49 l.j 10893e00 <_end+0x88fdf0> |
10002ce0: 56 21 22 00 *unknown* |
10002ce4: 22 55 44 49 *unknown* |
10002ce8: 56 21 22 00 *unknown* |
10002cec: 22 55 4e 4b *unknown* |
10002cf0: 4e 4f 57 4e *unknown* |
10002cf4: 22 00 72 65 *unknown* |
10002cf8: 63 75 72 73 *unknown* |
10002cfc: 69 76 65 5f *unknown* |
10002d00: 69 6e 74 20 *unknown* |
10002d04: 3d 3d 20 30 *unknown* |
10002d08: 00 0a 54 65 l.j 10297e9c <_end+0x293e8c> |
10002d0c: 73 74 3a 0a *unknown* |
10002d10: 00 31 2e 20 l.j 10c4e590 <_end+0xc4a580> |
10002d14: 49 6e 69 74 *unknown* |
10002d18: 69 61 6c 69 *unknown* |
10002d1c: 73 65 64 20 *unknown* |
10002d20: 64 61 74 61 *unknown* |
10002d24: 0a 00 76 61 *unknown* |
10002d28: 72 20 3d 3d *unknown* |
10002d2c: 20 30 78 31 *unknown* |
10002d30: 32 33 34 00 *unknown* |
10002d34: 74 65 73 74 *unknown* |
10002d38: 2e 63 00 75 *unknown* |
10002d3c: 76 61 72 20 *unknown* |
10002d40: 3d 3d 20 30 *unknown* |
10002d44: 78 30 00 32 *unknown* |
10002d48: 2e 20 4d 75 *unknown* |
10002d4c: 6c 74 69 70 *unknown* |
10002d50: 6c 79 0a 00 *unknown* |
10002d54: 76 61 72 20 *unknown* |
10002d58: 3d 3d 20 31 *unknown* |
10002d5c: 33 39 38 30 *unknown* |
10002d60: 00 76 61 72 l.j 11d9b328 <_end+0x1d97318> |
10002d64: 20 3d 3d 20 *unknown* |
10002d68: 2d 33 00 76 *unknown* |
10002d6c: 61 72 20 3d *unknown* |
10002d70: 3d 20 2d 36 *unknown* |
10002d74: 35 00 76 61 *unknown* |
10002d78: 72 20 3d 3d *unknown* |
10002d7c: 20 28 2d 35 *unknown* |
10002d80: 2a 2d 31 33 *unknown* |
10002d84: 29 00 76 61 *unknown* |
10002d88: 72 20 3d 3d *unknown* |
10002d8c: 20 28 2d 31 *unknown* |
10002d90: 32 33 31 32 *unknown* |
10002d94: 33 34 31 35 *unknown* |
10002d98: 2a 39 36 36 *unknown* |
10002d9c: 34 35 36 33 *unknown* |
10002da0: 29 00 33 2e *unknown* |
10002da4: 20 44 69 76 *unknown* |
10002da8: 69 64 65 0a *unknown* |
10002dac: 00 76 61 72 l.j 11d9b374 <_end+0x1d97364> |
10002db0: 20 3d 3d 20 *unknown* |
10002db4: 32 37 39 36 *unknown* |
10002db8: 00 76 61 72 l.j 11d9b380 <_end+0x1d97370> |
10002dbc: 20 3d 3d 20 *unknown* |
10002dc0: 39 36 00 76 *unknown* |
10002dc4: 61 72 20 3d *unknown* |
10002dc8: 3d 20 2d 36 *unknown* |
10002dcc: 37 00 34 2e *unknown* |
10002dd0: 20 53 68 69 *unknown* |
10002dd4: 66 74 20 6c *unknown* |
10002dd8: 65 66 74 0a *unknown* |
10002ddc: 00 76 61 72 l.j 11d9b3a4 <_end+0x1d97394> |
10002de0: 20 3d 3d 20 *unknown* |
10002de4: 30 78 38 30 *unknown* |
10002de8: 30 30 30 30 *unknown* |
10002dec: 30 30 00 35 *unknown* |
10002df0: 2e 20 53 68 *unknown* |
10002df4: 69 66 74 20 *unknown* |
10002df8: 72 69 67 68 *unknown* |
10002dfc: 74 0a 00 75 *unknown* |
10002e00: 76 61 72 20 *unknown* |
10002e04: 3d 3d 20 30 *unknown* |
10002e08: 78 34 30 30 *unknown* |
10002e0c: 30 30 30 30 *unknown* |
10002e10: 30 00 75 76 *unknown* |
10002e14: 61 72 20 3d *unknown* |
10002e18: 3d 20 30 78 *unknown* |
10002e1c: 30 30 30 30 *unknown* |
10002e20: 30 30 30 31 *unknown* |
10002e24: 00 36 2e 20 l.j 10d8e6a4 <_end+0xd8a694> |
10002e28: 53 68 69 66 *unknown* |
10002e2c: 74 20 72 69 *unknown* |
10002e30: 67 68 74 20 *unknown* |
10002e34: 61 72 69 74 *unknown* |
10002e38: 68 6d 65 74 *unknown* |
10002e3c: 69 63 0a 00 *unknown* |
10002e40: 76 61 72 20 *unknown* |
10002e44: 3d 3d 20 30 *unknown* |
10002e48: 78 43 30 30 *unknown* |
10002e4c: 30 30 30 30 *unknown* |
10002e50: 30 00 37 2e *unknown* |
10002e54: 20 53 69 67 *unknown* |
10002e58: 6e 65 64 20 *unknown* |
10002e5c: 63 6f 6d 70 *unknown* |
10002e60: 61 72 69 73 *unknown* |
10002e64: 69 6f 6e 0a *unknown* |
10002e68: 00 76 61 72 l.j 11d9b430 <_end+0x1d97420> |
10002e6c: 20 3c 20 31 *unknown* |
10002e70: 00 76 61 72 l.j 11d9b438 <_end+0x1d97428> |
10002e74: 20 3c 20 78 *unknown* |
10002e78: 00 21 28 76 l.j 1084d050 <_end+0x849040> |
10002e7c: 61 72 20 3e *unknown* |
10002e80: 20 78 29 00 *unknown* |
10002e84: 76 61 72 20 *unknown* |
10002e88: 3e 20 78 00 *unknown* |
10002e8c: 78 20 3c 3d *unknown* |
10002e90: 20 76 61 72 *unknown* |
10002e94: 00 38 2e 20 l.j 10e0e714 <_end+0xe0a704> |
10002e98: 57 6f 72 64 *unknown* |
10002e9c: 20 61 63 63 *unknown* |
10002ea0: 65 73 73 0a *unknown* |
10002ea4: 00 75 76 61 l.j 11d60828 <_end+0x1d5c818> |
10002ea8: 72 20 3d 3d *unknown* |
10002eac: 20 30 78 31 *unknown* |
10002eb0: 32 33 34 35 *unknown* |
10002eb4: 36 37 38 00 *unknown* |
10002eb8: 73 77 20 3d *unknown* |
10002ebc: 3d 20 30 78 *unknown* |
10002ec0: 35 36 37 38 *unknown* |
10002ec4: 00 2a 70 73 l.j 10a9f090 <_end+0xa9b080> |
10002ec8: 77 2b 2b 20 *unknown* |
10002ecc: 3d 3d 20 30 *unknown* |
10002ed0: 78 31 32 33 *unknown* |
10002ed4: 34 00 2a 70 *unknown* |
10002ed8: 73 77 2b 2b *unknown* |
10002edc: 20 3d 3d 20 *unknown* |
10002ee0: 30 78 35 36 *unknown* |
10002ee4: 37 38 00 2a *unknown* |
10002ee8: 70 73 77 2b *unknown* |
10002eec: 2b 20 3d 3d *unknown* |
10002ef0: 20 30 78 63 *unknown* |
10002ef4: 61 66 65 00 *unknown* |
10002ef8: 2a 70 73 77 *unknown* |
10002efc: 2b 2b 20 3d *unknown* |
10002f00: 3d 20 30 78 *unknown* |
10002f04: 62 61 62 65 *unknown* |
10002f08: 00 39 2e 20 l.j 10e4e788 <_end+0xe4a778> |
10002f0c: 42 79 74 65 *unknown* |
10002f10: 20 61 63 63 *unknown* |
10002f14: 65 73 73 0a *unknown* |
10002f18: 00 73 62 20 l.j 11cdb798 <_end+0x1cd7788> |
10002f1c: 3d 3d 20 30 *unknown* |
10002f20: 78 37 38 00 *unknown* |
10002f24: 2a 70 73 62 *unknown* |
10002f28: 2b 2b 20 3d *unknown* |
10002f2c: 3d 20 30 78 *unknown* |
10002f30: 31 32 00 2a *unknown* |
10002f34: 70 73 62 2b *unknown* |
10002f38: 2b 20 3d 3d *unknown* |
10002f3c: 20 30 78 33 *unknown* |
10002f40: 34 00 2a 70 *unknown* |
10002f44: 73 62 2b 2b *unknown* |
10002f48: 20 3d 3d 20 *unknown* |
10002f4c: 30 78 35 36 *unknown* |
10002f50: 00 2a 70 73 l.j 10a9f11c <_end+0xa9b10c> |
10002f54: 62 2b 2b 20 *unknown* |
10002f58: 3d 3d 20 30 *unknown* |
10002f5c: 78 37 38 00 *unknown* |
10002f60: 75 76 61 72 *unknown* |
10002f64: 20 3d 3d 20 *unknown* |
10002f68: 30 78 61 62 *unknown* |
10002f6c: 33 34 35 36 *unknown* |
10002f70: 37 38 00 75 *unknown* |
10002f74: 76 61 72 20 *unknown* |
10002f78: 3d 3d 20 30 *unknown* |
10002f7c: 78 61 62 63 *unknown* |
10002f80: 64 35 36 37 *unknown* |
10002f84: 38 00 75 76 *unknown* |
10002f88: 61 72 20 3d *unknown* |
10002f8c: 3d 20 30 78 *unknown* |
10002f90: 61 62 63 64 *unknown* |
10002f94: 65 66 37 38 *unknown* |
10002f98: 00 75 76 61 l.j 11d6091c <_end+0x1d5c90c> |
10002f9c: 72 20 3d 3d *unknown* |
10002fa0: 20 30 78 61 *unknown* |
10002fa4: 62 63 64 65 *unknown* |
10002fa8: 66 30 31 00 *unknown* |
10002fac: 31 30 2e 20 *unknown* |
10002fb0: 43 6f 6d 70 *unknown* |
10002fb4: 61 72 69 73 *unknown* |
10002fb8: 69 6f 6e 0a *unknown* |
10002fbc: 00 2d 20 49 l.j 10b4b0e0 <_end+0xb470d0> |
10002fc0: 6e 63 6f 72 *unknown* |
10002fc4: 72 65 63 74 *unknown* |
10002fc8: 20 63 6f 6d *unknown* |
10002fcc: 70 61 72 69 *unknown* |
10002fd0: 73 69 6f 6e *unknown* |
10002fd4: 0a 00 00 00 *unknown* |
/rtl/sim/ram.v
0,0 → 1,113
//----------------------------------------------------------------- |
// Module: ram - dual port block RAM |
//----------------------------------------------------------------- |
module ram |
( |
// Port A |
input clka_i /*verilator public*/, |
input ena_i /*verilator public*/, |
input [3:0] wea_i /*verilator public*/, |
input [31:2] addra_i /*verilator public*/, |
input [31:0] dataa_i /*verilator public*/, |
output [31:0] dataa_o /*verilator public*/, |
|
// Port B |
input clkb_i /*verilator public*/, |
input enb_i /*verilator public*/, |
input [3:0] web_i /*verilator public*/, |
input [31:2] addrb_i /*verilator public*/, |
input [31:0] datab_i /*verilator public*/, |
output [31:0] datab_o /*verilator public*/ |
); |
|
//----------------------------------------------------------------- |
// Params |
//----------------------------------------------------------------- |
parameter [31:0] block_count = 6; |
parameter [31:0] SIZE = 14; |
|
//----------------------------------------------------------------- |
// Instantiation |
//----------------------------------------------------------------- |
|
ram_dp8 |
#( |
.WIDTH(8), |
.SIZE(SIZE) |
) |
u0 |
( |
.aclk_i(clka_i), |
.aadr_i(addra_i[SIZE+2-1:2]), |
.adat_o(dataa_o[7:0]), |
.adat_i(dataa_i[7:0]), |
.awr_i(wea_i[0]), |
|
.bclk_i(clkb_i), |
.badr_i(addrb_i[SIZE+2-1:2]), |
.bdat_o(datab_o[7:0]), |
.bdat_i(datab_i[7:0]), |
.bwr_i(web_i[0]) |
); |
|
ram_dp8 |
#( |
.WIDTH(8), |
.SIZE(SIZE) |
) |
u1 |
( |
.aclk_i(clka_i), |
.aadr_i(addra_i[SIZE+2-1:2]), |
.adat_o(dataa_o[15:8]), |
.adat_i(dataa_i[15:8]), |
.awr_i(wea_i[1]), |
|
.bclk_i(clkb_i), |
.badr_i(addrb_i[SIZE+2-1:2]), |
.bdat_o(datab_o[15:8]), |
.bdat_i(datab_i[15:8]), |
.bwr_i(web_i[1]) |
); |
|
ram_dp8 |
#( |
.WIDTH(8), |
.SIZE(SIZE) |
) |
u2 |
( |
.aclk_i(clka_i), |
.aadr_i(addra_i[SIZE+2-1:2]), |
.adat_o(dataa_o[23:16]), |
.adat_i(dataa_i[23:16]), |
.awr_i(wea_i[2]), |
|
.bclk_i(clkb_i), |
.badr_i(addrb_i[SIZE+2-1:2]), |
.bdat_o(datab_o[23:16]), |
.bdat_i(datab_i[23:16]), |
.bwr_i(web_i[2]) |
); |
|
ram_dp8 |
#( |
.WIDTH(8), |
.SIZE(SIZE) |
) |
u3 |
( |
.aclk_i(clka_i), |
.aadr_i(addra_i[SIZE+2-1:2]), |
.adat_o(dataa_o[31:24]), |
.adat_i(dataa_i[31:24]), |
.awr_i(wea_i[3]), |
|
.bclk_i(clkb_i), |
.badr_i(addrb_i[SIZE+2-1:2]), |
.bdat_o(datab_o[31:24]), |
.bdat_i(datab_i[31:24]), |
.bwr_i(web_i[3]) |
); |
|
endmodule |
/rtl/sim/top.cpp
0,0 → 1,232
//----------------------------------------------------------------- |
// AltOR32 |
// Alternative Lightweight OpenRisc |
// V2.0 |
// Ultra-Embedded.com |
// Copyright 2011 - 2013 |
// |
// Email: admin@ultra-embedded.com |
// |
// License: LGPL |
//----------------------------------------------------------------- |
// |
// Copyright (C) 2011 - 2013 Ultra-Embedded.com |
// |
// This source file may be used and distributed without |
// restriction provided that this copyright statement is not |
// removed from the file and that any derivative work contains |
// the original copyright notice and the associated disclaimer. |
// |
// This source file is free software; you can redistribute it |
// and/or modify it under the terms of the GNU Lesser General |
// Public License as published by the Free Software Foundation; |
// either version 2.1 of the License, or (at your option) any |
// later version. |
// |
// This source is distributed in the hope that it will be |
// useful, but WITHOUT ANY WARRANTY; without even the implied |
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR |
// PURPOSE. See the GNU Lesser General Public License for more |
// details. |
// |
// You should have received a copy of the GNU Lesser General |
// Public License along with this source; if not, write to the |
// Free Software Foundation, Inc., 59 Temple Place, Suite 330, |
// Boston, MA 02111-1307 USA |
//----------------------------------------------------------------- |
#include <stdio.h> |
#include <unistd.h> |
#include <math.h> |
#include <time.h> |
|
#include "top_if.h" |
|
#include "Vtop__Syms.h" |
#include "verilated.h" |
|
#if VM_TRACE |
#include <verilated_vcd_c.h> |
#endif |
|
//----------------------------------------------------------------- |
// Defines |
//----------------------------------------------------------------- |
#define MEMORY_START 0x10000000 |
#define MEMORY_SIZE (1024 * 1024) |
|
#define OR32_BUBBLE_OPCODE 0xFC000000 |
|
#define CPU_INSTANCE top->v->u_cpu->u1_cpu |
|
//----------------------------------------------------------------- |
// Locals |
//----------------------------------------------------------------- |
static Vtop *top; |
static unsigned int _stop_pc = 0xFFFFFFFF; |
|
#if VM_TRACE |
static unsigned int main_time = 0; |
static VerilatedVcdC* tfp; |
#endif |
|
//----------------------------------------------------------------- |
// top_init |
//----------------------------------------------------------------- |
int top_init(void) |
{ |
top = new Vtop(); |
|
#if VM_TRACE |
// If verilator was invoked with --trace |
Verilated::traceEverOn(true); |
VL_PRINTF("Enabling GTKWave Trace Output...\n"); |
tfp = new VerilatedVcdC; |
top->trace (tfp, 99); |
tfp->open ("wave_dump.vcd"); |
#endif |
|
// Initial |
top->clk_i = 0; |
top->rst_i = 1; |
top->intr_i = 0; |
top->eval(); |
|
// Reset |
top->clk_i = 1; |
top->rst_i = 1; |
top->eval(); |
|
top->clk_i = 0; |
top->rst_i = 0; |
top->eval(); |
|
return 0; |
} |
|
//----------------------------------------------------------------- |
// top_load |
//----------------------------------------------------------------- |
int top_load(unsigned int addr, unsigned char val) |
{ |
if (addr >= (MEMORY_SIZE - MEMORY_START)) |
return -1; |
|
addr -= MEMORY_START; |
|
switch (addr & 0x3) |
{ |
case 0: |
top->v->u_ram->u3->ram[addr >> 2] = val; |
break; |
case 1: |
top->v->u_ram->u2->ram[addr >> 2] = val; |
break; |
case 2: |
top->v->u_ram->u1->ram[addr >> 2] = val; |
break; |
case 3: |
top->v->u_ram->u0->ram[addr >> 2] = val; |
break; |
} |
|
return 0; |
} |
//----------------------------------------------------------------- |
// top_setbreakpoint |
//----------------------------------------------------------------- |
int top_setbreakpoint(int bp, unsigned int pc) |
{ |
if (bp != 0) |
return -1; |
else |
{ |
_stop_pc = pc; |
return 0; |
} |
} |
//----------------------------------------------------------------- |
// top_run |
//----------------------------------------------------------------- |
int top_run(unsigned int pc, int cycles, int intr_after_cycles) |
{ |
int current_cycle = 0; |
|
// Run until fault or number of cycles completed |
while (!Verilated::gotFinish() && !top->fault_o && (current_cycle < cycles || cycles == -1)) |
{ |
// CLK->L |
top->clk_i = 0; |
top->eval(); |
|
#if VM_TRACE |
if (tfp) tfp->dump (main_time++); |
#endif |
|
// CLK->H |
top->clk_i = 1; |
top->eval(); |
|
#if VM_TRACE |
if (tfp) tfp->dump (main_time++); |
#endif |
|
// Get current executing instruction PC |
unsigned int pc = CPU_INSTANCE->u_exec->get_pc_ex(); |
unsigned int opcode = CPU_INSTANCE->u_exec->get_opcode_ex(); |
|
#ifdef INST_TRACE |
// Instruction trace - decode instruction opcode to text |
if (opcode != OR32_BUBBLE_OPCODE) |
printf("%08x: %02x %02x %02x %02x\n", pc, (opcode >> 24) & 0xFF, (opcode >> 16) & 0xFF, (opcode >> 8) & 0xFF, (opcode >> 0) & 0xFF); |
#endif |
|
// Generate interrupt after a certain number of cycles? |
if (intr_after_cycles >= 0 && intr_after_cycles == current_cycle) |
{ |
top->intr_i = 1; |
intr_after_cycles = -1; |
} |
else |
top->intr_i = 0; |
|
current_cycle++; |
|
// Breakpoint hit? |
if (_stop_pc == pc || top->break_o) |
{ |
if (_stop_pc == pc) |
printf("Stopped at breakpoint 0x%x\n", _stop_pc); |
printf("Cycles = %d\n", current_cycle); |
return TOP_RES_BREAKPOINT; |
} |
} |
|
printf("Cycles = %d\n", current_cycle); |
|
// Fault |
if (top->fault_o) |
{ |
printf("FAULT PC %x!\n", CPU_INSTANCE->u_exec->get_pc_ex()); |
return TOP_RES_FAULT; |
} |
// Number of cycles reached |
else if (current_cycle >= cycles) |
return TOP_RES_MAX_CYCLES; |
// No error |
else |
return TOP_RES_OK; |
} |
//----------------------------------------------------------------- |
// top_done |
//----------------------------------------------------------------- |
void top_done(void) |
{ |
top->final(); |
#if VM_TRACE |
if (tfp) |
{ |
tfp->close(); |
tfp = NULL; |
} |
#endif |
} |
/rtl/sim/main.cpp
0,0 → 1,258
//----------------------------------------------------------------- |
// AltOR32 |
// Alternative Lightweight OpenRisc |
// V2.0 |
// Ultra-Embedded.com |
// Copyright 2011 - 2013 |
// |
// Email: admin@ultra-embedded.com |
// |
// License: LGPL |
//----------------------------------------------------------------- |
// |
// Copyright (C) 2011 - 2013 Ultra-Embedded.com |
// |
// This source file may be used and distributed without |
// restriction provided that this copyright statement is not |
// removed from the file and that any derivative work contains |
// the original copyright notice and the associated disclaimer. |
// |
// This source file is free software; you can redistribute it |
// and/or modify it under the terms of the GNU Lesser General |
// Public License as published by the Free Software Foundation; |
// either version 2.1 of the License, or (at your option) any |
// later version. |
// |
// This source is distributed in the hope that it will be |
// useful, but WITHOUT ANY WARRANTY; without even the implied |
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR |
// PURPOSE. See the GNU Lesser General Public License for more |
// details. |
// |
// You should have received a copy of the GNU Lesser General |
// Public License along with this source; if not, write to the |
// Free Software Foundation, Inc., 59 Temple Place, Suite 330, |
// Boston, MA 02111-1307 USA |
//----------------------------------------------------------------- |
#include <stdio.h> |
#include <unistd.h> |
|
#include "top_if.h" |
#include "verilated.h" |
|
#ifdef INCLUDE_ELF_SUPPORT |
#include <libelf.h> |
#include <fcntl.h> |
#include <gelf.h> |
#endif |
|
//----------------------------------------------------------------- |
// Defines |
//----------------------------------------------------------------- |
#define MEM_BASE 0x10000000 |
#define MEM_EXEC_OFFSET 0x100 |
|
//----------------------------------------------------------------- |
// Locals |
//----------------------------------------------------------------- |
|
//----------------------------------------------------------------- |
// elf_load |
//----------------------------------------------------------------- |
#ifdef INCLUDE_ELF_SUPPORT |
static int elf_load(const char *filename, unsigned int *startAddr) |
{ |
int fd; |
Elf * e; |
Elf_Kind ek; |
Elf_Scn *scn; |
Elf_Data *data; |
Elf32_Shdr *shdr; |
size_t shstrndx; |
|
if (elf_version ( EV_CURRENT ) == EV_NONE) |
return 0; |
|
if ((fd = open ( filename , O_RDONLY , 0)) < 0) |
return 0; |
|
if ((e = elf_begin ( fd , ELF_C_READ, NULL )) == NULL) |
return 0; |
|
ek = elf_kind ( e ); |
if (ek != ELF_K_ELF) |
return 0; |
|
// Get section name header index |
if (elf_getshdrstrndx(e, &shstrndx)!=0) |
return 0; |
|
int section_idx = 0; |
while ((scn = elf_getscn(e, section_idx)) != NULL) |
{ |
shdr = elf32_getshdr(scn); |
|
// Section which need loading (.text, .bss, .data, etc) |
if ((shdr->sh_type == SHT_PROGBITS || shdr->sh_type == SHT_NOBITS) && |
(shdr->sh_flags & SHF_EXECINSTR || shdr->sh_flags & SHF_ALLOC) |
) |
{ |
data = elf_getdata(scn, NULL); |
|
// .text section? |
if (elf_strptr(e, shstrndx, shdr->sh_name) && startAddr && |
strcmp(elf_strptr(e, shstrndx, shdr->sh_name), ".text") == 0) |
{ |
*startAddr = shdr->sh_addr + MEM_EXEC_OFFSET; |
} |
|
printf("Memory: 0x%x - 0x%x (Size=%dKB) [%s]\n", shdr->sh_addr, shdr->sh_addr + shdr->sh_size - 1, shdr->sh_size / 1024, elf_strptr(e, shstrndx, shdr->sh_name)); |
|
if (shdr->sh_type == SHT_PROGBITS) |
{ |
int i; |
for (i=0;i<shdr->sh_size;i++) |
top_load(shdr->sh_addr + i, ((unsigned char*)data->d_buf)[i]); |
} |
} |
|
section_idx++; |
} |
|
elf_end ( e ); |
close ( fd ); |
|
return 1; |
} |
#endif |
|
//----------------------------------------------------------------- |
// main |
//----------------------------------------------------------------- |
int main(int argc, char **argv, char **env) |
{ |
int c; |
int err; |
unsigned int loadAddr = MEM_BASE; |
unsigned int execAddr = MEM_BASE + MEM_EXEC_OFFSET; |
unsigned int breakAddr = 0xFFFFFFFF; |
char *filename = NULL; |
int help = 0; |
int exitcode = 0; |
int cycles = -1; |
int intr_after = -1; |
|
Verilated::commandArgs(argc, argv); |
|
while ((c = getopt (argc, argv, "f:l:c:i:b:e:")) != -1) |
{ |
switch(c) |
{ |
case 'l': |
loadAddr = strtoul(optarg, NULL, 0); |
break; |
case 'f': |
filename = optarg; |
break; |
case 'c': |
cycles = strtoul(optarg, NULL, 0); |
break; |
case 'i': |
intr_after = strtoul(optarg, NULL, 0); |
break; |
case 'b': |
breakAddr = strtoul(optarg, NULL, 0); |
break; |
case '?': |
default: |
help = 1; |
break; |
} |
} |
|
if (loadAddr < MEM_BASE) |
{ |
fprintf (stderr,"Load address incorrect (0x%x)\n", loadAddr); |
exit(-1); |
} |
|
if (help || filename == NULL) |
{ |
fprintf (stderr,"Usage:\n"); |
fprintf (stderr,"-t = Enable program trace\n"); |
fprintf (stderr,"-l 0xnnnn = Executable load address\n"); |
fprintf (stderr,"-f filename = Executable to load\n"); |
fprintf (stderr,"-c num = Max number of cycles\n"); |
fprintf (stderr,"-i num = Generate interrupt after num cycles\n"); |
fprintf (stderr,"-b addr = Break at address\n"); |
|
exit(0); |
} |
|
top_init(); |
|
if (strstr(filename, ".elf")) |
{ |
#ifdef INCLUDE_ELF_SUPPORT |
if (!elf_load(filename, &execAddr)) |
{ |
fprintf (stderr,"Error: Could not open ELF file %s\n", filename); |
exit(-1); |
} |
#else |
fprintf (stderr,"Error: ELF files not supported\n"); |
exit(-1); |
#endif |
} |
else |
{ |
FILE *f; |
|
printf("Opening %s\n", filename); |
f = fopen(filename, "rb"); |
if (f) |
{ |
long size; |
char *buf; |
|
// Get size |
fseek(f, 0, SEEK_END); |
size = ftell(f); |
rewind(f); |
|
buf = (char*)malloc(size+1); |
if (buf) |
{ |
unsigned int addr; |
|
// Read file data in |
int len = fread(buf, 1, size, f); |
buf[len] = 0; |
|
printf("Loading to 0x%x\n", loadAddr); |
for (addr=0;addr<len;addr++) |
top_load(loadAddr + addr, buf[addr]); |
|
free(buf); |
fclose(f); |
} |
} |
else |
{ |
printf("Could not read file!\n"); |
exit(-1); |
} |
} |
|
// Setup breakpoint to stop at (or 0xFFFFFFFF if none) |
top_setbreakpoint(0, breakAddr); |
|
// Run |
err = top_run(execAddr, cycles, intr_after); |
|
// Cleanup |
top_done(); |
|
printf("Exit\n"); |
exit((err == TOP_RES_FAULT) ? 1 : 0); |
} |
/rtl/sim/top.v
0,0 → 1,227
//----------------------------------------------------------------- |
// AltOR32 |
// Alternative Lightweight OpenRisc |
// V2.0 |
// Ultra-Embedded.com |
// Copyright 2011 - 2013 |
// |
// Email: admin@ultra-embedded.com |
// |
// License: LGPL |
//----------------------------------------------------------------- |
// |
// Copyright (C) 2011 - 2013 Ultra-Embedded.com |
// |
// This source file may be used and distributed without |
// restriction provided that this copyright statement is not |
// removed from the file and that any derivative work contains |
// the original copyright notice and the associated disclaimer. |
// |
// This source file is free software; you can redistribute it |
// and/or modify it under the terms of the GNU Lesser General |
// Public License as published by the Free Software Foundation; |
// either version 2.1 of the License, or (at your option) any |
// later version. |
// |
// This source is distributed in the hope that it will be |
// useful, but WITHOUT ANY WARRANTY; without even the implied |
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR |
// PURPOSE. See the GNU Lesser General Public License for more |
// details. |
// |
// You should have received a copy of the GNU Lesser General |
// Public License along with this source; if not, write to the |
// Free Software Foundation, Inc., 59 Temple Place, Suite 330, |
// Boston, MA 02111-1307 USA |
//----------------------------------------------------------------- |
|
//----------------------------------------------------------------- |
// Module |
//----------------------------------------------------------------- |
module top |
( |
// Clocking & Reset |
input clk_i, |
input rst_i, |
// Fault Output |
output fault_o, |
// Break Output |
output break_o, |
// Interrupt Input |
input intr_i |
); |
|
//----------------------------------------------------------------- |
// Params |
//----------------------------------------------------------------- |
parameter CLK_KHZ = 8192; |
parameter BOOT_VECTOR = 32'h10000000; |
parameter ISR_VECTOR = 32'h10000000; |
|
//----------------------------------------------------------------- |
// Registers / Wires |
//----------------------------------------------------------------- |
wire [31:0] soc_addr; |
wire [31:0] soc_data_w; |
wire [31:0] soc_data_r; |
wire [3:0] soc_wr; |
wire soc_rd; |
wire soc_irq; |
|
wire[31:0] dmem_address; |
wire[31:0] dmem_data_w; |
wire[31:0] dmem_data_r; |
wire[3:0] dmem_wr; |
wire dmem_rd; |
wire dmem_burst; |
wire dmem_ack; |
reg dmem_req_r; |
|
wire[31:0] imem_addr; |
wire[31:0] imem_data; |
wire imem_rd; |
wire imem_burst; |
wire imem_ack; |
reg imem_req_r; |
|
//----------------------------------------------------------------- |
// Instantiation |
//----------------------------------------------------------------- |
|
// BlockRAM |
ram |
#( |
.block_count(128) // 1MB |
) |
u_ram |
( |
.clka_i(clk_i), |
.ena_i(1'b1), |
.wea_i(4'b0), |
.addra_i(imem_addr[31:2]), |
.dataa_i(32'b0), |
.dataa_o(imem_data), |
|
.clkb_i(clk_i), |
.enb_i(1'b1), |
.web_i(dmem_wr), |
.addrb_i(dmem_address[31:2]), |
.datab_i(dmem_data_w), |
.datab_o(dmem_data_r) |
); |
|
|
// CPU |
cpu_if |
#( |
.CLK_KHZ(CLK_KHZ), |
.BOOT_VECTOR(32'h10000000), |
.ISR_VECTOR(32'h10000000), |
.ENABLE_ICACHE("ENABLED"), |
.ENABLE_DCACHE("ENABLED"), |
.REGISTER_FILE_TYPE("SIMULATION") |
) |
u_cpu |
( |
// General - clocking & reset |
.clk_i(clk_i), |
.rst_i(rst_i), |
.fault_o(fault_o), |
.break_o(break_o), |
.nmi_i(1'b0), |
.intr_i(soc_irq), |
|
// Instruction Memory 0 (0x10000000 - 0x10FFFFFF) |
.imem0_addr_o(imem_addr), |
.imem0_rd_o(imem_rd), |
.imem0_burst_o(imem_burst), |
.imem0_data_in_i(imem_data), |
.imem0_accept_i(1'b1), |
.imem0_ack_i(imem_ack), |
|
// Data Memory 0 (0x10000000 - 0x10FFFFFF) |
.dmem0_addr_o(dmem_address), |
.dmem0_data_o(dmem_data_w), |
.dmem0_data_i(dmem_data_r), |
.dmem0_wr_o(dmem_wr), |
.dmem0_rd_o(dmem_rd), |
.dmem0_accept_i(1'b1), |
.dmem0_burst_o(dmem_burst), |
.dmem0_ack_i(dmem_ack), |
|
// Data Memory 1 (0x11000000 - 0x11FFFFFF) |
.dmem1_addr_o(), |
.dmem1_data_o(), |
.dmem1_data_i(32'b0), |
.dmem1_wr_o(), |
.dmem1_rd_o(), |
.dmem1_accept_i(1'b1), |
.dmem1_burst_o(/*open*/), |
.dmem1_ack_i(1'b1), |
|
// Data Memory 2 (0x12000000 - 0x12FFFFFF) |
.dmem2_addr_o(soc_addr), |
.dmem2_data_o(soc_data_w), |
.dmem2_data_i(soc_data_r), |
.dmem2_wr_o(soc_wr), |
.dmem2_rd_o(soc_rd), |
.dmem2_accept_i(1'b1), |
.dmem2_burst_o(/*open*/), |
.dmem2_ack_i(1'b1) |
); |
|
// CPU SOC |
soc |
#( |
.CLK_KHZ(CLK_KHZ), |
.ENABLE_SYSTICK_TIMER("ENABLED"), |
.ENABLE_HIGHRES_TIMER("ENABLED"), |
.EXTERNAL_INTERRUPTS(1) |
) |
u_soc |
( |
// General - clocking & reset |
.clk_i(clk_i), |
.rst_i(rst_i), |
.ext_intr_i(1'b0), |
.intr_o(soc_irq), |
|
// Memory Port |
.io_addr_i(soc_addr), |
.io_data_i(soc_data_w), |
.io_data_o(soc_data_r), |
.io_wr_i(soc_wr), |
.io_rd_i(soc_rd) |
); |
|
// Ack |
always @(posedge clk_i or posedge rst_i) |
begin |
if (rst_i == 1'b1) |
begin |
imem_req_r <= 1'b0; |
end |
else |
begin |
imem_req_r <= imem_rd; |
end |
end |
|
assign imem_ack = imem_req_r; |
|
// Ack |
always @(posedge clk_i or posedge rst_i) |
begin |
if (rst_i == 1'b1) |
begin |
dmem_req_r <= 1'b0; |
end |
else |
begin |
dmem_req_r <= dmem_rd | (|dmem_wr); |
end |
end |
|
assign dmem_ack = dmem_req_r; |
|
endmodule |
/rtl/sim/top_if.h
0,0 → 1,21
#ifndef __TOP_IF_H__ |
#define __TOP_IF_H__ |
|
//-------------------------------------------------------------------- |
// Defines |
//-------------------------------------------------------------------- |
#define TOP_RES_FAULT -1 |
#define TOP_RES_OK 0 |
#define TOP_RES_MAX_CYCLES 1 |
#define TOP_RES_BREAKPOINT 2 |
|
//-------------------------------------------------------------------- |
// Prototypes |
//-------------------------------------------------------------------- |
int top_init(void); |
int top_load(unsigned int addr, unsigned char val); |
void top_done(void); |
int top_run(unsigned int pc, int cycles, int intr_after_cycles); |
int top_setbreakpoint(int bp, unsigned int pc); |
|
#endif |
/rtl/sim/test_image.elf
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
rtl/sim/test_image.elf
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: rtl/sim/test_image.bin
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: rtl/sim/test_image.bin
===================================================================
--- rtl/sim/test_image.bin (nonexistent)
+++ rtl/sim/test_image.bin (revision 27)
rtl/sim/test_image.bin
Property changes :
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: rtl/sim/makefile
===================================================================
--- rtl/sim/makefile (nonexistent)
+++ rtl/sim/makefile (revision 27)
@@ -0,0 +1,67 @@
+
+# Default binary to load & run
+TEST_IMAGE ?= test_image.bin
+SIMARGS ?=
+CYCLES ?= -1
+STOP_AT ?= 0xFFFFFFFF
+
+# Default core to simulate
+RTL_CORE ?= cpu
+CORE_FILENAME ?= altor32.v
+
+# Waveform trace disabled by default
+TRACE?= 0
+
+# Enable debug output
+DEBUG?= 0
+
+# Enable instruction trace
+INST_TRACE?= 0
+
+# Top module (without .v extension)
+TOP_MODULE = top
+
+# Additional modules which can't be auto found
+ADDITIONAL_MODULES = ../$(RTL_CORE)/$(CORE_FILENAME)
+
+# CPP Source Files
+SRC_CPP = main.cpp top.cpp
+
+# Source directories
+INC_DIRS = -I../$(RTL_CORE) -I../soc -I../peripheral
+
+# Build directory
+BUILD_DIR = build
+
+VERILATOR_OPTS =
+
+ifeq ($(TRACE),1)
+ VERILATOR_OPTS += --trace
+endif
+
+ifeq ($(DEBUG),1)
+ VERILATOR_OPTS += +define+CONF_CORE_DEBUG+
+endif
+
+ifeq ($(INST_TRACE),1)
+ VERILATOR_OPTS += -CFLAGS "-DINST_TRACE"
+endif
+
+VERILATOR_OPTS += +define+SIMULATION+
+
+all: run
+
+compile: clean
+ verilator --cc $(TOP_MODULE).v $(ADDITIONAL_MODULES) $(SRC_CPP) $(INC_DIRS) +define+CONF_TARGET_SIM+ --exe -Mdir $(BUILD_DIR) $(VERILATOR_OPTS)
+ make -j -f V$(TOP_MODULE).mk -C $(BUILD_DIR)
+
+run: compile
+ ./$(BUILD_DIR)/V$(TOP_MODULE) -b $(STOP_AT) -c $(CYCLES) -f $(TEST_IMAGE) $(SIMARGS)
+
+ifeq ($(TRACE),1)
+view:
+ gtkwave wave_dump.vcd gtksettings.sav
+endif
+
+clean :
+ -rm -rf $(BUILD_DIR) wave_dump.vcd
Index: rtl/sim/ram_dp8.v
===================================================================
--- rtl/sim/ram_dp8.v (nonexistent)
+++ rtl/sim/ram_dp8.v (revision 27)
@@ -0,0 +1,74 @@
+
+//-----------------------------------------------------------------
+// Module: ram_dp8 - dual port block RAM
+//-----------------------------------------------------------------
+module ram_dp8
+(
+ aclk_i,
+ aadr_i,
+ adat_i,
+ awr_i,
+ adat_o,
+
+ bclk_i,
+ badr_i,
+ bdat_i,
+ bwr_i,
+ bdat_o
+);
+
+//-----------------------------------------------------------------
+// Params
+//-----------------------------------------------------------------
+parameter [31:0] WIDTH = 8;
+parameter [31:0] SIZE = 14;
+
+//-----------------------------------------------------------------
+// I/O
+//-----------------------------------------------------------------
+input aclk_i /*verilator public*/;
+output [(WIDTH - 1):0] adat_o /*verilator public*/;
+input [(WIDTH - 1):0] adat_i /*verilator public*/;
+input [(SIZE - 1):0] aadr_i /*verilator public*/;
+input awr_i /*verilator public*/;
+input bclk_i /*verilator public*/;
+output [(WIDTH - 1):0] bdat_o /*verilator public*/;
+input [(WIDTH - 1):0] bdat_i /*verilator public*/;
+input [(SIZE - 1):0] badr_i /*verilator public*/;
+input bwr_i /*verilator public*/;
+
+//-----------------------------------------------------------------
+// Registers
+//-----------------------------------------------------------------
+/* verilator lint_off MULTIDRIVEN */
+reg [(WIDTH - 1):0] ram [((2<< (SIZE-1)) - 1):0] /*verilator public*/;
+/* verilator lint_on MULTIDRIVEN */
+
+reg [(SIZE - 1):0] rd_addr_a;
+reg [(SIZE - 1):0] rd_addr_b;
+wire [(WIDTH - 1):0] adat_o;
+wire [(WIDTH - 1):0] bdat_o;
+
+//-----------------------------------------------------------------
+// Processes
+//-----------------------------------------------------------------
+always @ (posedge aclk_i)
+begin
+ if (awr_i == 1'b1)
+ ram[aadr_i] <= adat_i;
+ rd_addr_a <= aadr_i;
+end
+always @ (posedge bclk_i)
+begin
+ if (bwr_i == 1'b1)
+ ram[badr_i] <= bdat_i;
+ rd_addr_b <= badr_i;
+end
+
+//-------------------------------------------------------------------
+// Combinatorial
+//-------------------------------------------------------------------
+assign adat_o = ram[rd_addr_a];
+assign bdat_o = ram[rd_addr_b];
+
+endmodule
Index: rtl/peripheral/intr_defs.v
===================================================================
--- rtl/peripheral/intr_defs.v (nonexistent)
+++ rtl/peripheral/intr_defs.v (revision 27)
@@ -0,0 +1,44 @@
+//-----------------------------------------------------------------
+// AltOR32
+// Alternative Lightweight OpenRisc
+// V2.0
+// Ultra-Embedded.com
+// Copyright 2011 - 2013
+//
+// Email: admin@ultra-embedded.com
+//
+// License: LGPL
+//-----------------------------------------------------------------
+//
+// Copyright (C) 2011 - 2013 Ultra-Embedded.com
+//
+// This source file may be used and distributed without
+// restriction provided that this copyright statement is not
+// removed from the file and that any derivative work contains
+// the original copyright notice and the associated disclaimer.
+//
+// This source file is free software; you can redistribute it
+// and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation;
+// either version 2.1 of the License, or (at your option) any
+// later version.
+//
+// This source is distributed in the hope that it will be
+// useful, but WITHOUT ANY WARRANTY; without even the implied
+// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+// PURPOSE. See the GNU Lesser General Public License for more
+// details.
+//
+// You should have received a copy of the GNU Lesser General
+// Public License along with this source; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+// Boston, MA 02111-1307 USA
+//-----------------------------------------------------------------
+
+//-----------------------------------------------------------------
+// Registers
+//-----------------------------------------------------------------
+`define IRQ_MASK_SET 8'h00
+`define IRQ_MASK_CLR 8'h04
+`define IRQ_STATUS 8'h08
+ `define IRQ_EXT_FIRST (8)
Index: rtl/peripheral/timer_defs.v
===================================================================
--- rtl/peripheral/timer_defs.v (nonexistent)
+++ rtl/peripheral/timer_defs.v (revision 27)
@@ -0,0 +1,42 @@
+//-----------------------------------------------------------------
+// AltOR32
+// Alternative Lightweight OpenRisc
+// V2.0
+// Ultra-Embedded.com
+// Copyright 2011 - 2013
+//
+// Email: admin@ultra-embedded.com
+//
+// License: LGPL
+//-----------------------------------------------------------------
+//
+// Copyright (C) 2011 - 2013 Ultra-Embedded.com
+//
+// This source file may be used and distributed without
+// restriction provided that this copyright statement is not
+// removed from the file and that any derivative work contains
+// the original copyright notice and the associated disclaimer.
+//
+// This source file is free software; you can redistribute it
+// and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation;
+// either version 2.1 of the License, or (at your option) any
+// later version.
+//
+// This source is distributed in the hope that it will be
+// useful, but WITHOUT ANY WARRANTY; without even the implied
+// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+// PURPOSE. See the GNU Lesser General Public License for more
+// details.
+//
+// You should have received a copy of the GNU Lesser General
+// Public License along with this source; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+// Boston, MA 02111-1307 USA
+//-----------------------------------------------------------------
+
+//-----------------------------------------------------------------
+// Registers
+//-----------------------------------------------------------------
+`define TIMER_SYSTICK_VAL 8'h00
+`define TIMER_HIRES 8'h04
Index: rtl/peripheral/intr_periph.v
===================================================================
--- rtl/peripheral/intr_periph.v (nonexistent)
+++ rtl/peripheral/intr_periph.v (revision 27)
@@ -0,0 +1,230 @@
+//-----------------------------------------------------------------
+// AltOR32
+// Alternative Lightweight OpenRisc
+// V2.0
+// Ultra-Embedded.com
+// Copyright 2011 - 2013
+//
+// Email: admin@ultra-embedded.com
+//
+// License: LGPL
+//-----------------------------------------------------------------
+//
+// Copyright (C) 2011 - 2013 Ultra-Embedded.com
+//
+// This source file may be used and distributed without
+// restriction provided that this copyright statement is not
+// removed from the file and that any derivative work contains
+// the original copyright notice and the associated disclaimer.
+//
+// This source file is free software; you can redistribute it
+// and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation;
+// either version 2.1 of the License, or (at your option) any
+// later version.
+//
+// This source is distributed in the hope that it will be
+// useful, but WITHOUT ANY WARRANTY; without even the implied
+// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+// PURPOSE. See the GNU Lesser General Public License for more
+// details.
+//
+// You should have received a copy of the GNU Lesser General
+// Public License along with this source; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+// Boston, MA 02111-1307 USA
+//-----------------------------------------------------------------
+
+//-----------------------------------------------------------------
+// Includes
+//-----------------------------------------------------------------
+`include "intr_defs.v"
+
+//-----------------------------------------------------------------
+// Module:
+//-----------------------------------------------------------------
+module intr_periph
+(
+ // General - Clocking & Reset
+ clk_i,
+ rst_i,
+ intr_o,
+
+ // Interrupts
+ intr0_i,
+ intr1_i,
+ intr2_i,
+ intr3_i,
+ intr4_i,
+ intr5_i,
+ intr6_i,
+ intr7_i,
+ intr_ext_i,
+
+ // Peripheral bus
+ addr_i,
+ data_o,
+ data_i,
+ wr_i,
+ rd_i
+);
+
+//-----------------------------------------------------------------
+// Params
+//-----------------------------------------------------------------
+parameter EXTERNAL_INTERRUPTS = 1;
+parameter INTERRUPT_COUNT = EXTERNAL_INTERRUPTS + 8;
+
+//-----------------------------------------------------------------
+// I/O
+//-----------------------------------------------------------------
+input clk_i /*verilator public*/;
+input rst_i /*verilator public*/;
+output intr_o /*verilator public*/;
+
+input intr0_i /*verilator public*/;
+input intr1_i /*verilator public*/;
+input intr2_i /*verilator public*/;
+input intr3_i /*verilator public*/;
+input intr4_i /*verilator public*/;
+input intr5_i /*verilator public*/;
+input intr6_i /*verilator public*/;
+input intr7_i /*verilator public*/;
+input [(EXTERNAL_INTERRUPTS - 1):0] intr_ext_i /*verilator public*/;
+input [7:0] addr_i /*verilator public*/;
+output [31:0] data_o /*verilator public*/;
+input [31:0] data_i /*verilator public*/;
+input [3:0] wr_i /*verilator public*/;
+input rd_i /*verilator public*/;
+
+//-----------------------------------------------------------------
+// Registers / Wires
+//-----------------------------------------------------------------
+reg [31:0] data_o;
+reg intr_o;
+
+// IRQ Status
+wire intr_in;
+reg [INTERRUPT_COUNT-1:0] irq_status;
+reg [INTERRUPT_COUNT-1:0] irq_mask;
+reg [INTERRUPT_COUNT-1:0] v_irq_status;
+
+//-----------------------------------------------------------------
+// Peripheral Register Write
+//-----------------------------------------------------------------
+always @ (posedge rst_i or posedge clk_i )
+begin
+ if (rst_i == 1'b1)
+ begin
+ irq_status <= {(INTERRUPT_COUNT){1'b0}};
+ irq_mask <= {(INTERRUPT_COUNT){1'b0}};
+ intr_o <= 1'b0;
+ end
+ else
+ begin
+
+ // Get current IRQ status
+ v_irq_status = irq_status;
+
+ // IRQ0
+ if (intr0_i == 1'b1)
+ v_irq_status[0] = 1'b1;
+
+ // IRQ1
+ if (intr1_i == 1'b1)
+ v_irq_status[1] = 1'b1;
+
+ // IRQ2
+ if (intr2_i == 1'b1)
+ v_irq_status[2] = 1'b1;
+
+ // IRQ3
+ if (intr3_i == 1'b1)
+ v_irq_status[3] = 1'b1;
+
+ // IRQ4
+ if (intr4_i == 1'b1)
+ v_irq_status[4] = 1'b1;
+
+ // IRQ5
+ if (intr5_i == 1'b1)
+ v_irq_status[5] = 1'b1;
+
+ // IRQ6
+ if (intr6_i == 1'b1)
+ v_irq_status[6] = 1'b1;
+
+ // IRQ7
+ if (intr7_i == 1'b1)
+ v_irq_status[7] = 1'b1;
+
+ // External interrupts
+ begin : ext_ints_loop
+ integer i;
+ for (i=0; i< EXTERNAL_INTERRUPTS; i=i+1)
+ begin
+ if (intr_ext_i[i] == 1'b1)
+ v_irq_status[(`IRQ_EXT_FIRST + i)] = 1'b1;
+ end
+ end
+
+ // Update IRQ status
+ irq_status <= v_irq_status;
+
+ // Generate interrupt based on masked status
+ intr_o <= ((v_irq_status & irq_mask) != {(INTERRUPT_COUNT){1'b0}}) ? 1'b1 : 1'b0;
+
+ // Write Cycle
+ if (wr_i != 4'b0000)
+ begin
+ case (addr_i)
+
+ `IRQ_MASK_SET :
+ irq_mask <= (irq_mask | data_i[INTERRUPT_COUNT-1:0]);
+
+ `IRQ_MASK_CLR :
+ irq_mask <= (irq_mask & ~ (data_i[INTERRUPT_COUNT-1:0]));
+
+ `IRQ_STATUS : // (IRQ Acknowledge)
+ irq_status <= (v_irq_status & ~ (data_i[INTERRUPT_COUNT-1:0]));
+
+ default :
+ ;
+ endcase
+ end
+ end
+end
+
+//-----------------------------------------------------------------
+// Peripheral Register Read
+//-----------------------------------------------------------------
+always @ (posedge rst_i or posedge clk_i )
+begin
+ if (rst_i == 1'b1)
+ begin
+ data_o <= 32'h00000000;
+ end
+ else
+ begin
+ // Read cycle?
+ if (rd_i == 1'b1)
+ begin
+ case (addr_i[7:0])
+
+ `IRQ_MASK_SET :
+ data_o <= {{(32-INTERRUPT_COUNT){1'b0}}, irq_mask};
+
+ `IRQ_MASK_CLR :
+ data_o <= {{(32-INTERRUPT_COUNT){1'b0}}, irq_mask};
+
+ `IRQ_STATUS :
+ data_o <= {{(32-INTERRUPT_COUNT){1'b0}}, irq_status};
+
+ default :
+ data_o <= 32'h00000000;
+ endcase
+ end
+ end
+end
+
+endmodule
Index: rtl/peripheral/timer_periph.v
===================================================================
--- rtl/peripheral/timer_periph.v (nonexistent)
+++ rtl/peripheral/timer_periph.v (revision 27)
@@ -0,0 +1,279 @@
+//-----------------------------------------------------------------
+// AltOR32
+// Alternative Lightweight OpenRisc
+// V2.0
+// Ultra-Embedded.com
+// Copyright 2011 - 2013
+//
+// Email: admin@ultra-embedded.com
+//
+// License: LGPL
+//-----------------------------------------------------------------
+//
+// Copyright (C) 2011 - 2013 Ultra-Embedded.com
+//
+// This source file may be used and distributed without
+// restriction provided that this copyright statement is not
+// removed from the file and that any derivative work contains
+// the original copyright notice and the associated disclaimer.
+//
+// This source file is free software; you can redistribute it
+// and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation;
+// either version 2.1 of the License, or (at your option) any
+// later version.
+//
+// This source is distributed in the hope that it will be
+// useful, but WITHOUT ANY WARRANTY; without even the implied
+// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+// PURPOSE. See the GNU Lesser General Public License for more
+// details.
+//
+// You should have received a copy of the GNU Lesser General
+// Public License along with this source; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+// Boston, MA 02111-1307 USA
+//-----------------------------------------------------------------
+
+//-----------------------------------------------------------------
+// Includes
+//-----------------------------------------------------------------
+`include "timer_defs.v"
+
+//-----------------------------------------------------------------
+// Module:
+//-----------------------------------------------------------------
+module timer_periph
+(
+ // General - Clocking & Reset
+ clk_i,
+ rst_i,
+
+ // Interrupts
+ intr_systick_o,
+ intr_hires_o,
+
+ // Peripheral bus
+ addr_i,
+ data_o,
+ data_i,
+ wr_i,
+ rd_i
+);
+
+//-----------------------------------------------------------------
+// Params
+//-----------------------------------------------------------------
+parameter [31:0] CLK_KHZ = 12288;
+parameter SYSTICK_INTR_MS = 1;
+parameter ENABLE_SYSTICK_TIMER = "ENABLED";
+parameter ENABLE_HIGHRES_TIMER = "ENABLED";
+
+//-----------------------------------------------------------------
+// I/O
+//-----------------------------------------------------------------
+input clk_i /*verilator public*/;
+input rst_i /*verilator public*/;
+
+output intr_systick_o /*verilator public*/;
+output intr_hires_o /*verilator public*/;
+
+input [7:0] addr_i /*verilator public*/;
+output [31:0] data_o /*verilator public*/;
+input [31:0] data_i /*verilator public*/;
+input [3:0] wr_i /*verilator public*/;
+input rd_i /*verilator public*/;
+
+//-----------------------------------------------------------------
+// Registers / Wires
+//-----------------------------------------------------------------
+
+reg [31:0] data_o;
+
+// Systick Timer
+reg systick_event;
+reg [31:0] systick_count;
+reg [31:0] systick_clk_count;
+
+// Hi-res system clock tick counter
+reg hr_timer_intr;
+reg [31:0] hr_timer_cnt;
+reg [31:0] hr_timer_match;
+
+//-----------------------------------------------------------------
+// Systick
+//-----------------------------------------------------------------
+generate
+if (ENABLE_SYSTICK_TIMER == "ENABLED")
+begin
+
+ // SysTick Timer (1 ms resolution)
+ always @ (posedge rst_i or posedge clk_i )
+ begin
+ if (rst_i == 1'b1)
+ begin
+ systick_count <= 32'h00000000;
+ systick_clk_count <= 32'h00000000;
+ systick_event <= 1'b0;
+ end
+ else
+ begin
+ systick_event <= 1'b0;
+
+ if (systick_clk_count == CLK_KHZ)
+ begin
+ systick_count <= (systick_count + 1);
+ systick_event <= 1'b1;
+ systick_clk_count <= 32'h00000000;
+ end
+ else
+ systick_clk_count <= (systick_clk_count + 1);
+ end
+ end
+
+ // SysTick Interrupt
+ integer systick_event_count;
+ reg systick_event_intr;
+
+ always @ (posedge rst_i or posedge clk_i )
+ begin
+ if (rst_i == 1'b1)
+ begin
+ systick_event_count <= 0;
+ systick_event_intr <= 1'b0;
+ end
+ else
+ begin
+ systick_event_intr <= 1'b0;
+
+ if (systick_event)
+ begin
+ systick_event_count <= (systick_event_count + 1);
+
+ if (systick_event_count == (SYSTICK_INTR_MS-1))
+ begin
+ systick_event_intr <= 1'b1;
+ systick_event_count <= 0;
+ end
+ end
+ end
+ end
+
+ assign intr_systick_o = systick_event_intr;
+end
+else
+begin
+ // Systick disabled
+ always @ (posedge rst_i or posedge clk_i )
+ begin
+ if (rst_i == 1'b1)
+ systick_count <= 32'h00000000;
+ else
+ systick_count <= 32'h00000000;
+ end
+
+ assign intr_systick_o = 1'b0;
+end
+endgenerate
+
+//-----------------------------------------------------------------
+// Hi Resolution Timer
+//-----------------------------------------------------------------
+generate
+if (ENABLE_HIGHRES_TIMER == "ENABLED")
+begin
+
+ always @ (posedge rst_i or posedge clk_i)
+ begin
+ if (rst_i == 1'b1)
+ begin
+ hr_timer_cnt <= 32'h00000000;
+ hr_timer_intr <= 1'b0;
+ end
+ else
+ begin
+ hr_timer_intr <= 1'b0;
+
+ // Clock tick counter
+ hr_timer_cnt <= (hr_timer_cnt + 1);
+
+ // Hi-res Timer IRQ
+ if ((hr_timer_match != 32'h00000000) && (hr_timer_match == hr_timer_cnt))
+ hr_timer_intr <= 1'b1;
+ end
+ end
+
+ assign intr_hires_o = hr_timer_intr;
+end
+else
+begin
+ // Hi resolution timer disabled
+ always @ (posedge rst_i or posedge clk_i )
+ begin
+ if (rst_i == 1'b1)
+ hr_timer_cnt <= 32'h00000000;
+ else
+ hr_timer_cnt <= 32'h00000000;
+ end
+
+ assign intr_hires_o = 1'b0;
+end
+endgenerate
+//-----------------------------------------------------------------
+// Peripheral Register Write
+//-----------------------------------------------------------------
+always @ (posedge rst_i or posedge clk_i )
+begin
+ if (rst_i == 1'b1)
+ begin
+ hr_timer_match <= 32'h00000000;
+ end
+ else
+ begin
+ // Write Cycle
+ if (wr_i != 4'b0000)
+ begin
+ case (addr_i)
+
+ `TIMER_HIRES :
+ hr_timer_match <= data_i;
+
+ default :
+ ;
+ endcase
+ end
+ end
+end
+
+//-----------------------------------------------------------------
+// Peripheral Register Read
+//-----------------------------------------------------------------
+always @ (posedge rst_i or posedge clk_i )
+begin
+ if (rst_i == 1'b1)
+ begin
+ data_o <= 32'h00000000;
+ end
+ else
+ begin
+ // Read cycle?
+ if (rd_i == 1'b1)
+ begin
+ case (addr_i[7:0])
+
+ // 32-bit systick/1ms counter
+ `TIMER_SYSTICK_VAL :
+ data_o <= systick_count;
+
+ // Hi res timer (clock rate)
+ `TIMER_HIRES :
+ data_o <= hr_timer_cnt;
+
+ default :
+ data_o <= 32'h00000000;
+ endcase
+ end
+ end
+end
+
+endmodule