URL
https://opencores.org/ocsvn/sparc64soc/sparc64soc/trunk
Subversion Repositories sparc64soc
Compare Revisions
- This comparison shows the changes necessary to convert path
/sparc64soc/trunk
- from Rev 5 to Rev 6
- ↔ Reverse comparison
Rev 5 → Rev 6
/os2wb/l1dir.v
32,10 → 32,10
wire dquery1= cpu && store && (!blockstore); |
wire dalloc0=(!cpu) && cacheable && (!invalidate) && load && (!prefetch); |
wire dalloc1= cpu && cacheable && (!invalidate) && load && (!prefetch); |
wire ddealloc0=((!cpu) && (ifill || cas || swap || strstore || (store && blockstore))) || |
( cpu && ((load && cacheable) || ifill || store || cas || swap || strload || strstore)); |
wire ddealloc1=( cpu && (ifill || cas || swap || strstore || (store && blockstore))) || |
((!cpu) && ((load && cacheable) || ifill || store || cas || swap || strload || strstore)); |
wire ddealloc0=((!cpu) && ((ifill && (!prefetch) && (!invalidate)) || cas || swap || strstore || (store && blockstore))) || |
( cpu && ((load && cacheable && (!prefetch) && (!invalidate)) || (ifill && (!prefetch) && (!invalidate)) || store || cas || swap || strload || strstore)); |
wire ddealloc1=( cpu && ((ifill && (!prefetch) && (!invalidate)) || cas || swap || strstore || (store && blockstore))) || |
((!cpu) && ((load && cacheable && (!prefetch) && (!invalidate)) || (ifill && (!prefetch) && (!invalidate)) || store || cas || swap || strload || strstore)); |
|
wire iquery0=0; |
wire iquery1=0; |
42,9 → 42,9
wire ialloc0=(!cpu) && cacheable && (!invalidate) && ifill; |
wire ialloc1= cpu && cacheable && (!invalidate) && ifill; |
wire idealloc0=((!cpu) && ((load && cacheable && (!prefetch) && (!invalidate)) || store || cas || swap || strstore)) || |
( cpu && ((load && cacheable && (!prefetch) && (!invalidate)) || ifill || store || cas || swap || strload || strstore)); |
( cpu && ((load && cacheable && (!prefetch) && (!invalidate)) || (ifill && (!prefetch) && (!invalidate)) || store || cas || swap || strload || strstore)); |
wire idealloc1=( cpu && ((load && cacheable && (!prefetch) && (!invalidate)) || store || cas || swap || strstore )) || |
((!cpu) && ((load && cacheable && (!prefetch) && (!invalidate)) || ifill || store || cas || swap || strload || strstore)); |
((!cpu) && ((load && cacheable && (!prefetch) && (!invalidate)) || (ifill && (!prefetch) && (!invalidate)) || store || cas || swap || strload || strstore)); |
|
|
wire [2:0] cpu0_dhit0; |
88,7 → 88,7
|
.index(address[10:4]), |
.way(way), |
.tag(address[39:11]), |
.tag(address[39:11]), |
.strobe(strobe), |
.query(dquery0), |
.allocate(dalloc0), |
/os2wb/os2wb_dual.v
1,1003 → 1,1118
`timescale 1ns / 1ps |
////////////////////////////////////////////////////////////////////////////////// |
// Company: (C) Athree, 2009 |
// Engineer: Dmitry Rozhdestvenskiy |
// Email dmitry.rozhdestvenskiy@srisc.com dmitryr@a3.spb.ru divx4log@narod.ru |
// |
// Design Name: Bridge from SPARC Core to Wishbone Master |
// Module Name: os2wb |
// Project Name: SPARC SoC single-core |
// |
// LICENSE: |
// This is a Free Hardware Design; you can redistribute it and/or |
// modify it under the terms of the GNU General Public License |
// version 2 as published by the Free Software Foundation. |
// The above named program 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 General Public License for more details. |
// |
////////////////////////////////////////////////////////////////////////////////// |
module os2wb_dual( |
input clk, |
input rstn, |
|
// Core interface |
input [ 4:0] pcx_req, |
input pcx_atom, |
input [123:0] pcx_data, |
output reg [ 4:0] pcx_grant, |
output reg cpx_ready, |
output reg [144:0] cpx_packet, |
|
// Wishbone master interface |
input [ 63:0] wb_data_i, |
input wb_ack, |
output reg wb_cycle, |
output reg wb_strobe, |
output reg wb_we, |
output reg [ 7:0] wb_sel, |
output reg [ 63:0] wb_addr, |
output reg [ 63:0] wb_data_o, |
|
// FPU interface |
output reg [123:0] fp_pcx, |
output reg fp_req, |
input [144:0] fp_cpx, |
input fp_rdy, |
|
// Ethernet interrupt, sensed on posedge, mapped to vector 'd29 |
input eth_int |
); |
|
reg [123:0] pcx_packet_d; // Latched incoming PCX packet |
reg [123:0] pcx_packet_2nd; // Second packet for atomic (CAS) |
reg [ 4:0] pcx_req_d; // Latched request |
reg pcx_atom_d; // Latched atomic flasg |
reg [ 4:0] state; // FSM state |
reg [144:0] cpx_packet_1; // First CPX packet |
reg [144:0] cpx_packet_2; // Second CPX packet (for atomics and cached IFILLs) |
reg cpx_two_packet; // CPX answer is two-packet (!=atomic, SWAP has atomic==0 and answer is two-packet) |
|
wire [111:0] inval_vect0; // Invalidate, instr/data, way |
wire [111:0] inval_vect1; // IFill may cause two D lines invalidation at a time |
|
wire [1:0] othercachehit; |
wire [1:0] othercpuhit; |
wire [1:0] wayval0; |
wire [1:0] wayval1; |
|
`define TEST_DRAM_1 5'b00000 |
`define TEST_DRAM_2 5'b00001 |
`define TEST_DRAM_3 5'b00010 |
`define TEST_DRAM_4 5'b00011 |
`define INIT_DRAM_1 5'b00100 |
`define INIT_DRAM_2 5'b00101 |
`define WAKEUP 5'b00110 |
`define PCX_IDLE 5'b00111 |
`define GOT_PCX_REQ 5'b01000 |
`define PCX_REQ_2ND 5'b01001 |
`define PCX_REQ_STEP1 5'b01010 |
`define PCX_REQ_STEP1_1 5'b01011 |
`define PCX_REQ_STEP2 5'b01100 |
`define PCX_REQ_STEP2_1 5'b01101 |
`define PCX_REQ_STEP3 5'b01110 |
`define PCX_REQ_STEP3_1 5'b01111 |
`define PCX_REQ_STEP4 5'b10000 |
`define PCX_REQ_STEP4_1 5'b10001 |
`define PCX_BIS 5'b10010 |
`define PCX_BIS_1 5'b10011 |
`define PCX_BIS_2 5'b10100 |
`define CPX_READY_1 5'b10101 |
`define CPX_READY_2 5'b10110 |
`define PCX_REQ_STEP1_2 5'b10111 |
`define PCX_UNKNOWN 5'b11000 |
`define PCX_FP_1 5'b11001 |
`define PCX_FP_2 5'b11010 |
`define FP_WAIT 5'b11011 |
`define CPX_FP 5'b11100 |
`define CPX_SEND_ETH_IRQ 5'b11101 |
`define CPX_INT_VEC_DIS 5'b11110 |
`define PCX_REQ_CAS_COMPARE 5'b11111 |
|
`define MEM_SIZE 64'h00000000_10000000 |
|
`define TEST_DRAM 1 |
`define DEBUGGING 1 |
|
reg cache_init; |
wire [3:0] dcache0_hit; |
wire [3:0] dcache1_hit; |
wire [3:0] icache_hit; |
reg multi_hit; |
reg multi_hit1; |
reg eth_int_d; |
reg eth_int_send; |
reg eth_int_sent; |
reg [3:0] cnt; |
|
// PCX channel FIFO |
wire [129:0] pcx_data_fifo; |
wire pcx_fifo_empty; |
reg [ 4:0] pcx_req_1; |
reg [ 4:0] pcx_req_2; |
reg pcx_atom_1; |
reg pcx_atom_2; |
reg pcx_data_123_d; |
|
always @(posedge clk) |
begin |
pcx_req_1<=pcx_req; |
pcx_atom_1<=pcx_atom; |
pcx_atom_2<=pcx_atom_1; |
pcx_req_2<=pcx_atom_1 ? pcx_req_1:5'b0; |
pcx_grant<=(pcx_req_1 | pcx_req_2); |
pcx_data_123_d<=pcx_data[123]; |
end |
|
pcx_fifo pcx_fifo_inst( |
// FIFO should be first word fall-through |
// It has no full flag as the core will send only limited number of requests, |
// in original design we used it 32 words deep |
// Just make it deeper if you experience overflow - |
// you can't just send no grant on full because the core expects immediate |
// grant for at least two requests for each zone |
.aclr(!rstn), |
.clock(clk), |
.data({pcx_atom_1,pcx_req_1,pcx_data}), |
.rdreq(fifo_rd), |
.wrreq((pcx_req_1!=5'b00000 && pcx_data[123]) || (pcx_atom_2 && pcx_data_123_d)), |
// Second atomic packet for FPU may be invalid, but should be sent to FPU |
// so if the first atomic packet is valid we latch both |
.empty(pcx_fifo_empty), |
.q(pcx_data_fifo) |
); |
// -------------------------- |
|
reg wb_ack_d; |
|
always @(posedge clk or negedge rstn) |
if(!rstn) |
eth_int_send<=0; |
else |
begin |
wb_ack_d<=wb_ack; |
eth_int_d<=eth_int; |
if(eth_int && !eth_int_d) |
eth_int_send<=1; |
else |
if(eth_int_sent) |
eth_int_send<=0; |
end |
|
reg fifo_rd; |
wire [123:0] pcx_packet; |
assign pcx_packet=pcx_data_fifo[123:0]; |
|
always @(posedge clk or negedge rstn) |
if(rstn==0) |
begin |
if(`TEST_DRAM) |
state<=`TEST_DRAM_1; |
else |
state<=`INIT_DRAM_1; // DRAM initialization is mandatory! |
cpx_ready<=0; |
fifo_rd<=0; |
cpx_packet<=145'b0; |
wb_cycle<=0; |
wb_strobe<=0; |
wb_we<=0; |
wb_sel<=0; |
wb_addr<=64'b0; |
wb_data_o<=64'b0; |
pcx_packet_d<=124'b0; |
fp_pcx<=124'b0; |
fp_req<=0; |
end |
else |
case(state) |
`TEST_DRAM_1: |
begin |
wb_cycle<=1; |
wb_strobe<=1; |
wb_sel<=8'hFF; |
wb_we<=1; |
state<=`TEST_DRAM_2; |
end |
`TEST_DRAM_2: |
if(wb_ack) |
begin |
wb_strobe<=0; |
if(wb_addr<`MEM_SIZE-8) |
begin |
wb_addr[31:0]<=wb_addr[31:0]+8; |
wb_data_o<={wb_addr[31:0]+8,wb_addr[31:0]+8}; |
state<=`TEST_DRAM_1; |
end |
else |
begin |
state<=`TEST_DRAM_3; |
wb_cycle<=0; |
wb_sel<=0; |
wb_we<=0; |
wb_data_o<=64'b0; |
wb_addr<=64'b0; |
end |
end |
`TEST_DRAM_3: |
begin |
wb_cycle<=1; |
wb_strobe<=1; |
wb_sel<=8'hFF; |
state<=`TEST_DRAM_4; |
end |
`TEST_DRAM_4: |
if(wb_ack) |
begin |
wb_strobe<=0; |
if(wb_addr<`MEM_SIZE-8) |
begin |
if(wb_data_i=={wb_addr[31:0],wb_addr[31:0]}) |
begin |
wb_addr[31:0]<=wb_addr[31:0]+8; |
state<=`TEST_DRAM_3; |
end |
end |
else |
begin |
state<=`INIT_DRAM_1; |
wb_cycle<=0; |
wb_sel<=0; |
wb_we<=0; |
wb_data_o<=64'b0; |
wb_addr<=64'b0; |
end |
end |
`INIT_DRAM_1: |
begin |
wb_cycle<=1; |
wb_strobe<=1; |
wb_sel<=8'hFF; |
wb_we<=1; |
cache_init<=1; // We also init cache directories here |
state<=`INIT_DRAM_2; |
end |
`INIT_DRAM_2: |
if(wb_ack) |
begin |
wb_strobe<=0; |
if(wb_addr<`MEM_SIZE-8) |
begin |
wb_addr[31:0]<=wb_addr[31:0]+8; |
pcx_packet_d[64+11:64+4]<=pcx_packet_d[64+11:64+4]+1; // Address for cachedir init |
state<=`INIT_DRAM_1; |
end |
else |
begin |
state<=`WAKEUP; |
wb_cycle<=0; |
wb_sel<=0; |
wb_we<=0; |
cache_init<=0; |
wb_addr<=64'b0; |
end |
end |
`WAKEUP: |
begin |
cpx_packet<=145'h1700000000000000000000000000000010001; |
cpx_ready<=1; |
state<=`PCX_IDLE; |
end |
`PCX_IDLE: |
begin |
cnt<=0; |
cpx_packet<=145'b0; |
cpx_ready<=0; |
cpx_two_packet<=0; |
multi_hit<=0; |
multi_hit1<=0; |
if(eth_int_send) |
begin |
state<=`CPX_SEND_ETH_IRQ; |
eth_int_sent<=1; |
end |
else |
if(!pcx_fifo_empty) |
begin |
pcx_req_d<=pcx_data_fifo[128:124]; |
pcx_atom_d<=pcx_data_fifo[129]; |
fifo_rd<=1; |
state<=`GOT_PCX_REQ; |
end |
end |
`GOT_PCX_REQ: |
begin |
pcx_packet_d<=pcx_packet; |
if(`DEBUGGING) |
begin |
wb_sel[1:0]<=pcx_packet[113:112]; |
wb_sel[2]<=1; |
end |
if(pcx_packet[103:64]==40'h9800000800 && pcx_packet[122:118]==5'b00001) |
begin |
state<=`CPX_INT_VEC_DIS; |
fifo_rd<=0; |
end |
else |
if(pcx_atom_d==0) |
begin |
fifo_rd<=0; |
if(pcx_packet[122:118]==5'b01010) // FP req |
begin |
state<=`PCX_FP_1; |
pcx_packet_2nd[123]<=0; |
end |
else |
state<=`PCX_REQ_STEP1; |
end |
else |
state<=`PCX_REQ_2ND; |
end |
`PCX_REQ_2ND: |
begin |
pcx_packet_2nd<=pcx_packet; //Latch second packet for atomics |
if(`DEBUGGING) |
if(pcx_fifo_empty) |
wb_sel<=8'h67; |
fifo_rd<=0; |
if(pcx_packet_d[122:118]==5'b01010) // FP req |
state<=`PCX_FP_1; |
else |
state<=`PCX_REQ_STEP1; |
end |
`PCX_REQ_STEP1: |
begin |
if(pcx_packet_d[111]==1'b1) // Invalidate request |
begin |
cpx_packet_1[144]<=1; // Valid |
cpx_packet_1[143:140]<=4'b0100; // Invalidate reply is Store ACK |
cpx_packet_1[139]<=1; // L2 miss |
cpx_packet_1[138:137]<=0; // Error |
cpx_packet_1[136]<=pcx_packet_d[117]; // Non-cacheble |
cpx_packet_1[135:134]<=pcx_packet_d[113:112]; // Thread ID |
cpx_packet_1[133:131]<=0; // Way valid |
cpx_packet_1[130]<=((pcx_packet_d[122:118]==5'b10000) && (pcx_req_d==5'b10000)) ? 1:0; // Four byte fill |
cpx_packet_1[129]<=pcx_atom_d; |
cpx_packet_1[128]<=pcx_packet_d[110]; // Prefetch |
cpx_packet_1[127:0]<={2'b0,pcx_packet_d[109]/*BIS*/,pcx_packet_d[122:118]==5'b00000 ? 2'b01:2'b10,pcx_packet_d[64+5:64+4],3'b0,pcx_packet_d[64+11:64+6],112'b0}; |
state<=`CPX_READY_1; |
end |
else |
if(pcx_packet_d[122:118]!=5'b01001) // Not INT |
begin |
wb_cycle<=1'b1; |
wb_strobe<=1'b1; |
if((pcx_packet_d[122:118]==5'b00000 && !pcx_req_d[4]) || pcx_packet_d[122:118]==5'b00010 || pcx_packet_d[122:118]==5'b00100 || pcx_packet_d[122:118]==5'b00110) |
wb_addr<={pcx_req_d,19'b0,pcx_packet_d[103:64+4],4'b0000}; //DRAM load/streamload, CAS and SWAP always use DRAM and load first |
else |
if(pcx_packet_d[122:118]==5'b10000 && !pcx_req_d[4]) |
wb_addr<={pcx_req_d,19'b0,pcx_packet_d[103:64+5],5'b00000}; //DRAM ifill |
else |
if(pcx_packet_d[64+39:64+28]==12'hFFF && pcx_packet_d[64+27:64+24]!=4'b0) // flash remap FFF1->FFF8 |
wb_addr<={pcx_req_d,19'b0,pcx_packet_d[103:64+3]+37'h0000E00000,3'b000}; |
else |
wb_addr<={pcx_req_d,19'b0,pcx_packet_d[103:64+3],3'b000}; |
wb_data_o<=pcx_packet_d[63:0]; |
state<=`PCX_REQ_STEP1_1; |
end |
else |
if((pcx_packet_d[12:10]!=3'b000) && !pcx_packet_d[117]) // Not FLUSH int and not this core |
state<=`PCX_IDLE; |
else |
state<=`CPX_READY_1; |
case(pcx_packet_d[122:118]) // Packet type |
5'b00000://Load |
begin |
wb_we<=0; |
if(!pcx_req_d[4]) |
wb_sel<=8'b11111111; // DRAM requests are always 128 bit |
else |
case(pcx_packet_d[106:104]) //Size |
3'b000://Byte |
case(pcx_packet_d[64+2:64]) |
3'b000:wb_sel<=8'b10000000; |
3'b001:wb_sel<=8'b01000000; |
3'b010:wb_sel<=8'b00100000; |
3'b011:wb_sel<=8'b00010000; |
3'b100:wb_sel<=8'b00001000; |
3'b101:wb_sel<=8'b00000100; |
3'b110:wb_sel<=8'b00000010; |
3'b111:wb_sel<=8'b00000001; |
endcase |
3'b001://Halfword |
case(pcx_packet_d[64+2:64+1]) |
2'b00:wb_sel<=8'b11000000; |
2'b01:wb_sel<=8'b00110000; |
2'b10:wb_sel<=8'b00001100; |
2'b11:wb_sel<=8'b00000011; |
endcase |
3'b010://Word |
wb_sel<=(pcx_packet_d[64+2]==0) ? 8'b11110000:8'b00001111; |
3'b011://Doubleword |
wb_sel<=8'b11111111; |
3'b100://Quadword |
wb_sel<=8'b11111111; |
3'b111://Cacheline |
wb_sel<=8'b11111111; |
default: |
wb_sel<=8'b01011010; // Unreal eye-catching value for debug |
endcase |
end |
5'b00001://Store |
begin |
wb_we<=1; |
if(pcx_packet_d[110:109]!=2'b00) //Block (or init) store |
wb_sel<=8'b11111111; // Blocks are always 64 bit |
else |
case(pcx_packet_d[106:104]) //Size |
3'b000://Byte |
case(pcx_packet_d[64+2:64]) |
3'b000:wb_sel<=8'b10000000; |
3'b001:wb_sel<=8'b01000000; |
3'b010:wb_sel<=8'b00100000; |
3'b011:wb_sel<=8'b00010000; |
3'b100:wb_sel<=8'b00001000; |
3'b101:wb_sel<=8'b00000100; |
3'b110:wb_sel<=8'b00000010; |
3'b111:wb_sel<=8'b00000001; |
endcase |
3'b001://Halfword |
case(pcx_packet_d[64+2:64+1]) |
2'b00:wb_sel<=8'b11000000; |
2'b01:wb_sel<=8'b00110000; |
2'b10:wb_sel<=8'b00001100; |
2'b11:wb_sel<=8'b00000011; |
endcase |
3'b010://Word |
wb_sel<=(pcx_packet_d[64+2]==0) ? 8'b11110000:8'b00001111; |
3'b011://Doubleword |
wb_sel<=8'b11111111; |
default: |
if(`DEBUGGING) |
wb_sel<=8'b01011010; // Unreal eye-catching value for debug |
endcase |
end |
5'b00010://CAS |
begin |
wb_we<=0; //Load first |
wb_sel<=8'b11111111; // CAS loads are as cacheline |
end |
5'b00100://STRLOAD |
begin |
wb_we<=0; |
wb_sel<=8'b11111111; // Stream loads are always 128 bit |
end |
5'b00101://STRSTORE |
begin |
wb_we<=1; |
case(pcx_packet_d[106:104]) //Size |
3'b000://Byte |
case(pcx_packet_d[64+2:64]) |
3'b000:wb_sel<=8'b10000000; |
3'b001:wb_sel<=8'b01000000; |
3'b010:wb_sel<=8'b00100000; |
3'b011:wb_sel<=8'b00010000; |
3'b100:wb_sel<=8'b00001000; |
3'b101:wb_sel<=8'b00000100; |
3'b110:wb_sel<=8'b00000010; |
3'b111:wb_sel<=8'b00000001; |
endcase |
3'b001://Halfword |
case(pcx_packet_d[64+2:64+1]) |
2'b00:wb_sel<=8'b11000000; |
2'b01:wb_sel<=8'b00110000; |
2'b10:wb_sel<=8'b00001100; |
2'b11:wb_sel<=8'b00000011; |
endcase |
3'b010://Word |
wb_sel<=(pcx_packet_d[64+2]==0) ? 8'b11110000:8'b00001111; |
3'b011://Doubleword |
wb_sel<=8'b11111111; |
3'b100://Quadword |
wb_sel<=8'b11111111; |
3'b111://Cacheline |
wb_sel<=8'b11111111; |
default: |
wb_sel<=8'b01011010; // Unreal eye-catching value for debug |
endcase |
end |
5'b00110://SWAP/LDSTUB |
begin |
wb_we<=0; // Load first, as CAS |
wb_sel<=8'b11111111; // SWAP/LDSTUB loads are as cacheline |
end |
5'b01001://INT |
if(pcx_packet_d[117]) // Flush |
cpx_packet_1<={9'h171,pcx_packet_d[113:112],11'h0,pcx_packet_d[64+5:64+4],3'b0,pcx_packet_d[64+11:64+6],30'h0,pcx_packet_d[17:0],46'b0,pcx_packet_d[17:0]}; //FLUSH instruction answer |
else // Tread-to-thread interrupt |
cpx_packet_1<={9'h170,pcx_packet_d[113:112],52'h0,pcx_packet_d[17:0],46'h0,pcx_packet_d[17:0]}; |
//5'b01010: FP1 - processed by separate state |
//5'b01011: FP2 - processed by separate state |
//5'b01101: FWDREQ - not implemented |
//5'b01110: FWDREPL - not implemented |
5'b10000://IFILL |
begin |
wb_we<=0; |
if(pcx_req_d[4]) // I/O access |
wb_sel<=(pcx_packet_d[64+2]==0) ? 8'b11110000:8'b00001111; |
else |
wb_sel<=8'b11111111; |
end |
default: |
begin |
wb_we<=0; |
wb_sel<=8'b10101010; // Unreal eye-catching value for debug |
end |
endcase |
end |
`PCX_REQ_STEP1_1: |
state<=`PCX_REQ_STEP1_2; // Delay for L1 directory |
`PCX_REQ_STEP1_2: |
begin |
if(wb_ack || wb_ack_d) |
begin |
cpx_packet_1[144]<=1; // Valid |
cpx_packet_1[139]<=(pcx_packet_d[122:118]==5'b00000) || (pcx_packet_d[122:118]==5'b10000) ? 1:0; // L2 always miss on load and ifill |
cpx_packet_1[138:137]<=0; // Error |
cpx_packet_1[136]<=pcx_packet_d[117] || (pcx_packet_d[122:118]==5'b00001) ? 1:0; // Non-cacheble is set on store too |
cpx_packet_1[135:134]<=pcx_packet_d[113:112]; // Thread ID |
if((pcx_packet_d[122:118]==5'b00000 && !pcx_packet_d[117] && !pcx_packet_d[110]) || (pcx_packet_d[122:118]==5'b10000)) // Cacheble Load or IFill |
cpx_packet_1[133:131]<={othercachehit[0],wayval0}; |
else |
cpx_packet_1[133:131]<=3'b000; // Way valid |
if(pcx_packet_d[122:118]==5'b00100) // Strload |
cpx_packet_1[130]<=pcx_packet_d[106]; // A |
else |
if(pcx_packet_d[122:118]==5'b00101) // Stream store |
cpx_packet_1[130]<=pcx_packet_d[108]; // A |
else |
cpx_packet_1[130]<=((pcx_packet_d[122:118]==5'b10000) && pcx_req_d[4]) ? 1:0; // Four byte fill |
if(pcx_packet_d[122:118]==5'b00100) // Strload |
cpx_packet_1[129]<=pcx_packet_d[105]; // B |
else |
cpx_packet_1[129]<=pcx_atom_d || (pcx_packet_d[122:118]==5'b00110); // SWAP is single-packet but needs atom in CPX |
cpx_packet_1[128]<=pcx_packet_d[110] && pcx_packet_d[122:118]==5'b00000; // Prefetch |
cpx_packet_2[144]<=1; // Valid |
cpx_packet_2[139]<=0; // L2 miss |
cpx_packet_2[138:137]<=0; // Error |
cpx_packet_2[136]<=pcx_packet_d[117] || (pcx_packet_d[122:118]==5'b00001) ? 1:0; // Non-cacheble is set on store too |
cpx_packet_2[135:134]<=pcx_packet_d[113:112]; // Thread ID |
if(pcx_packet_d[122:118]==5'b10000) // IFill |
cpx_packet_2[133:131]<={othercachehit[1],wayval1}; |
else |
cpx_packet_2[133:131]<=3'b000; // Way valid |
cpx_packet_2[130]<=0; // Four byte fill |
cpx_packet_2[129]<=pcx_atom_d || (pcx_packet_d[122:118]==5'b00110) || ((pcx_packet_d[122:118]==5'b10000) && !pcx_req_d[4]); |
cpx_packet_2[128]<=0; // Prefetch |
wb_strobe<=0; |
wb_sel<=8'b0; |
wb_addr<=64'b0; |
wb_data_o<=64'b0; |
wb_we<=0; |
case(pcx_packet_d[122:118]) // Packet type |
5'b00000://Load |
begin |
cpx_packet_1[143:140]<=4'b0000; // Type |
if(!pcx_req_d[4]) |
begin |
cpx_packet_1[127:0]<={wb_data_i,wb_data_i}; |
state<=`PCX_REQ_STEP2; |
end |
else |
case(pcx_packet_d[106:104]) //Size |
3'b000://Byte |
begin |
case(pcx_packet_d[64+2:64]) |
3'b000:cpx_packet_1[127:0]<={wb_data_i[63:56],wb_data_i[63:56],wb_data_i[63:56],wb_data_i[63:56],wb_data_i[63:56],wb_data_i[63:56],wb_data_i[63:56],wb_data_i[63:56],wb_data_i[63:56],wb_data_i[63:56],wb_data_i[63:56],wb_data_i[63:56],wb_data_i[63:56],wb_data_i[63:56],wb_data_i[63:56],wb_data_i[63:56]}; |
3'b001:cpx_packet_1[127:0]<={wb_data_i[55:48],wb_data_i[55:48],wb_data_i[55:48],wb_data_i[55:48],wb_data_i[55:48],wb_data_i[55:48],wb_data_i[55:48],wb_data_i[55:48],wb_data_i[55:48],wb_data_i[55:48],wb_data_i[55:48],wb_data_i[55:48],wb_data_i[55:48],wb_data_i[55:48],wb_data_i[55:48],wb_data_i[55:48]}; |
3'b010:cpx_packet_1[127:0]<={wb_data_i[47:40],wb_data_i[47:40],wb_data_i[47:40],wb_data_i[47:40],wb_data_i[47:40],wb_data_i[47:40],wb_data_i[47:40],wb_data_i[47:40],wb_data_i[47:40],wb_data_i[47:40],wb_data_i[47:40],wb_data_i[47:40],wb_data_i[47:40],wb_data_i[47:40],wb_data_i[47:40],wb_data_i[47:40]}; |
3'b011:cpx_packet_1[127:0]<={wb_data_i[39:32],wb_data_i[39:32],wb_data_i[39:32],wb_data_i[39:32],wb_data_i[39:32],wb_data_i[39:32],wb_data_i[39:32],wb_data_i[39:32],wb_data_i[39:32],wb_data_i[39:32],wb_data_i[39:32],wb_data_i[39:32],wb_data_i[39:32],wb_data_i[39:32],wb_data_i[39:32],wb_data_i[39:32]}; |
3'b100:cpx_packet_1[127:0]<={wb_data_i[31:24],wb_data_i[31:24],wb_data_i[31:24],wb_data_i[31:24],wb_data_i[31:24],wb_data_i[31:24],wb_data_i[31:24],wb_data_i[31:24],wb_data_i[31:24],wb_data_i[31:24],wb_data_i[31:24],wb_data_i[31:24],wb_data_i[31:24],wb_data_i[31:24],wb_data_i[31:24],wb_data_i[31:24]}; |
3'b101:cpx_packet_1[127:0]<={wb_data_i[23:16],wb_data_i[23:16],wb_data_i[23:16],wb_data_i[23:16],wb_data_i[23:16],wb_data_i[23:16],wb_data_i[23:16],wb_data_i[23:16],wb_data_i[23:16],wb_data_i[23:16],wb_data_i[23:16],wb_data_i[23:16],wb_data_i[23:16],wb_data_i[23:16],wb_data_i[23:16],wb_data_i[23:16]}; |
3'b110:cpx_packet_1[127:0]<={wb_data_i[15: 8],wb_data_i[15: 8],wb_data_i[15: 8],wb_data_i[15: 8],wb_data_i[15: 8],wb_data_i[15: 8],wb_data_i[15: 8],wb_data_i[15: 8],wb_data_i[15: 8],wb_data_i[15: 8],wb_data_i[15: 8],wb_data_i[15: 8],wb_data_i[15: 8],wb_data_i[15: 8],wb_data_i[15: 8],wb_data_i[15: 8]}; |
3'b111:cpx_packet_1[127:0]<={wb_data_i[ 7: 0],wb_data_i[ 7: 0],wb_data_i[ 7: 0],wb_data_i[ 7: 0],wb_data_i[ 7: 0],wb_data_i[ 7: 0],wb_data_i[ 7: 0],wb_data_i[ 7: 0],wb_data_i[ 7: 0],wb_data_i[ 7: 0],wb_data_i[ 7: 0],wb_data_i[ 7: 0],wb_data_i[ 7: 0],wb_data_i[ 7: 0],wb_data_i[ 7: 0],wb_data_i[ 7: 0]}; |
endcase |
wb_cycle<=0; |
state<=`CPX_READY_1; |
end |
3'b001://Halfword |
begin |
case(pcx_packet_d[64+2:64+1]) |
2'b00:cpx_packet_1[127:0]<={wb_data_i[63:48],wb_data_i[63:48],wb_data_i[63:48],wb_data_i[63:48],wb_data_i[63:48],wb_data_i[63:48],wb_data_i[63:48],wb_data_i[63:48]}; |
2'b01:cpx_packet_1[127:0]<={wb_data_i[47:32],wb_data_i[47:32],wb_data_i[47:32],wb_data_i[47:32],wb_data_i[47:32],wb_data_i[47:32],wb_data_i[47:32],wb_data_i[47:32]}; |
2'b10:cpx_packet_1[127:0]<={wb_data_i[31:16],wb_data_i[31:16],wb_data_i[31:16],wb_data_i[31:16],wb_data_i[31:16],wb_data_i[31:16],wb_data_i[31:16],wb_data_i[31:16]}; |
2'b11:cpx_packet_1[127:0]<={wb_data_i[15: 0],wb_data_i[15: 0],wb_data_i[15: 0],wb_data_i[15: 0],wb_data_i[15: 0],wb_data_i[15: 0],wb_data_i[15: 0],wb_data_i[15: 0]}; |
endcase |
wb_cycle<=0; |
state<=`CPX_READY_1; |
end |
3'b010://Word |
begin |
if(pcx_packet_d[64+2]==0) |
cpx_packet_1[127:0]<={wb_data_i[63:32],wb_data_i[63:32],wb_data_i[63:32],wb_data_i[63:32]}; |
else |
cpx_packet_1[127:0]<={wb_data_i[31:0],wb_data_i[31:0],wb_data_i[31:0],wb_data_i[31:0]}; |
wb_cycle<=0; |
state<=`CPX_READY_1; |
end |
3'b011://Doubleword |
begin |
cpx_packet_1[127:0]<={wb_data_i,wb_data_i}; |
wb_cycle<=0; |
state<=`CPX_READY_1; |
end |
3'b100://Quadword |
begin |
cpx_packet_1[127:0]<={wb_data_i,wb_data_i}; |
wb_cycle<=0; |
state<=`CPX_READY_1; // 16 byte access to PROM should just duplicate the data |
end |
3'b111://Cacheline |
begin |
cpx_packet_1[127:0]<={wb_data_i,wb_data_i}; |
wb_cycle<=0; |
state<=`CPX_READY_1; // 16 byte access to PROM should just duplicate the data |
end |
default: |
begin |
cpx_packet_1[127:0]<={wb_data_i,wb_data_i}; |
wb_cycle<=0; |
state<=`PCX_UNKNOWN; |
end |
endcase |
end |
5'b00001://Store |
begin |
cpx_packet_1[143:140]<=4'b0100; // Type |
cpx_packet_1[127:0]<={2'b0,pcx_packet_d[109]/*BIS*/,2'b0,pcx_packet_d[64+5:64+4],3'b0,pcx_packet_d[64+11:64+6],inval_vect0}; |
// if((pcx_packet_d[110:109]==2'b01) && (pcx_packet_d[64+5:64]==0) && !inval_vect0[3] && !inval_vect1[3]) // Block init store |
// state<=`PCX_BIS; |
// else |
// begin |
wb_cycle<=0; |
state<=`CPX_READY_1; |
// end |
end |
5'b00010://CAS |
begin |
cpx_packet_1[143:140]<=4'b0000; // Load return for first packet |
cpx_packet_2[143:140]<=4'b0100; // Store ACK for second packet |
cpx_packet_2[127:0]<={5'b0,pcx_packet_d[64+5:64+4],3'b0,pcx_packet_d[64+11:64+6],inval_vect0}; |
cpx_packet_1[127:0]<={wb_data_i,wb_data_i}; |
state<=`PCX_REQ_STEP2; |
end |
5'b00100://STRLOAD |
begin |
cpx_packet_1[143:140]<=4'b0010; // Type |
cpx_packet_1[127:0]<={wb_data_i,wb_data_i}; |
state<=`PCX_REQ_STEP2; |
end |
5'b00101://STRSTORE |
begin |
cpx_packet_1[143:140]<=4'b0110; // Type |
cpx_packet_1[127:0]<={5'b0,pcx_packet_d[64+5:64+4],3'b0,pcx_packet_d[64+11:64+6],inval_vect0}; |
wb_cycle<=0; |
state<=`CPX_READY_1; |
end |
5'b00110://SWAP/LDSTUB |
begin |
cpx_packet_1[143:140]<=4'b0000; // Load return for first packet |
cpx_packet_2[143:140]<=4'b0100; // Store ACK for second packet |
cpx_packet_2[127:0]<={5'b0,pcx_packet_d[64+5:64+4],3'b0,pcx_packet_d[64+11:64+6],inval_vect0}; |
cpx_packet_1[127:0]<={wb_data_i,wb_data_i}; |
state<=`PCX_REQ_STEP2; |
end |
5'b10000://IFILL |
begin |
cpx_packet_1[143:140]<=4'b0001; // Type |
cpx_packet_2[143:140]<=4'b0001; // Type |
if(pcx_req_d[4]) // I/O access |
begin |
if(pcx_packet_d[64+2]==0) |
cpx_packet_1[127:0]<={wb_data_i[63:32],wb_data_i[63:32],wb_data_i[63:32],wb_data_i[63:32]}; |
else |
cpx_packet_1[127:0]<={wb_data_i[31:0],wb_data_i[31:0],wb_data_i[31:0],wb_data_i[31:0]}; |
state<=`CPX_READY_1; |
wb_cycle<=0; |
end |
else |
begin |
cpx_packet_1[127:0]<={wb_data_i,wb_data_i}; |
state<=`PCX_REQ_STEP2; |
end |
end |
default: |
begin |
wb_cycle<=0; |
state<=`PCX_UNKNOWN; |
end |
endcase |
end |
end |
`PCX_REQ_STEP2: // IFill, Load/strload, CAS, SWAP, LDSTUB - alwas load |
begin |
wb_strobe<=1'b1; |
if(pcx_packet_d[122:118]==5'b10000) |
wb_addr<={pcx_req_d,19'b0,pcx_packet_d[103:64+5],5'b01000}; |
else |
wb_addr<={pcx_req_d,19'b0,pcx_packet_d[103:64+4],4'b1000}; |
wb_sel<=8'b11111111; // It is always full width for subsequent IFill and load accesses |
state<=`PCX_REQ_STEP2_1; |
end |
`PCX_REQ_STEP2_1: |
if(wb_ack==1) |
begin |
wb_strobe<=0; |
wb_sel<=8'b0; |
wb_addr<=64'b0; |
wb_data_o<=64'b0; |
wb_we<=0; |
cpx_packet_1[63:0]<=wb_data_i; |
if((pcx_packet_d[122:118]!=5'b00000) && (pcx_packet_d[122:118]!=5'b00100)) |
if(pcx_packet_d[122:118]!=5'b00010) // IFill, SWAP |
state<=`PCX_REQ_STEP3; |
else |
state<=`PCX_REQ_CAS_COMPARE; // CAS |
else |
begin |
wb_cycle<=0; |
state<=`CPX_READY_1; |
end |
end |
`PCX_REQ_CAS_COMPARE: |
begin |
cpx_two_packet<=1; |
if(pcx_packet_d[106:104]==3'b010) // 32-bit |
case(pcx_packet_d[64+3:64+2]) |
2'b00:state<=cpx_packet_1[127:96]==pcx_packet_d[63:32] ? `PCX_REQ_STEP3:`CPX_READY_1; |
2'b01:state<=cpx_packet_1[95:64]==pcx_packet_d[63:32] ? `PCX_REQ_STEP3:`CPX_READY_1; |
2'b10:state<=cpx_packet_1[63:32]==pcx_packet_d[63:32] ? `PCX_REQ_STEP3:`CPX_READY_1; |
2'b11:state<=cpx_packet_1[31:0]==pcx_packet_d[63:32] ? `PCX_REQ_STEP3:`CPX_READY_1; |
endcase |
else |
if(pcx_packet_d[64+3]==0) |
state<=cpx_packet_1[127:64]==pcx_packet_d[63:0] ? `PCX_REQ_STEP3:`CPX_READY_1; |
else |
state<=cpx_packet_1[63:0]==pcx_packet_d[63:0] ? `PCX_REQ_STEP3:`CPX_READY_1; |
end |
`PCX_REQ_STEP3: // 256-bit IFILL; CAS, SWAP and LDSTUB store |
begin |
if(pcx_packet_d[122:118]==5'b10000) |
wb_addr<={pcx_req_d,19'b0,pcx_packet_d[103:64+5],5'b10000}; |
else |
wb_addr<={pcx_req_d,19'b0,pcx_packet_d[103:64+3],3'b000}; // CAS or SWAP save |
cpx_two_packet<=1; |
if(pcx_packet_d[122:118]==5'b10000) |
wb_we<=0; |
else |
wb_we<=1; |
wb_strobe<=1'b1; |
if(pcx_packet_d[122:118]==5'b00010) // CAS |
if(pcx_packet_d[106:104]==3'b010) |
wb_sel<=(pcx_packet_d[64+2]==0) ? 8'b11110000:8'b00001111; |
else |
wb_sel<=8'b11111111; //CASX |
else |
if(pcx_packet_d[122:118]==5'b00110) //SWAP or LDSTUB |
if(pcx_packet_d[106:104]==3'b000) //LDSTUB |
case(pcx_packet_d[64+2:64]) |
3'b000:wb_sel<=8'b10000000; |
3'b001:wb_sel<=8'b01000000; |
3'b010:wb_sel<=8'b00100000; |
3'b011:wb_sel<=8'b00010000; |
3'b100:wb_sel<=8'b00001000; |
3'b101:wb_sel<=8'b00000100; |
3'b110:wb_sel<=8'b00000010; |
3'b111:wb_sel<=8'b00000001; |
endcase |
else |
wb_sel<=(pcx_packet_d[64+2]==0) ? 8'b11110000:8'b00001111; ///SWAP is always 32-bit |
else |
wb_sel<=8'b11111111; // It is always full width for subsequent IFill accesses |
if(pcx_packet_d[122:118]==5'b00110) //SWAP or LDSTUB |
wb_data_o<={pcx_packet_d[63:32],pcx_packet_d[63:32]}; |
// wb_data_o<=pcx_packet_d[63:0]; |
else |
wb_data_o<=pcx_packet_2nd[63:0]; // CAS store second packet data |
// if(pcx_packet_d[106:104]==3'b010) |
// wb_data_o<={pcx_packet_2nd[63:32],pcx_packet_2nd[63:32]}; // CAS store second packet data |
// else |
// wb_data_o<=pcx_packet_2nd[63:0]; |
state<=`PCX_REQ_STEP3_1; |
end |
`PCX_REQ_STEP3_1: |
if(wb_ack==1) |
begin |
wb_strobe<=0; |
wb_sel<=8'b0; |
wb_addr<=64'b0; |
wb_we<=0; |
wb_data_o<=64'b0; |
if(pcx_packet_d[122:118]==5'b10000) // IFill |
begin |
cpx_packet_2[127:64]<=wb_data_i; |
state<=`PCX_REQ_STEP4; |
end |
else |
begin |
wb_cycle<=0; |
state<=`CPX_READY_1; |
end |
end |
`PCX_REQ_STEP4: // 256-bit IFILL only |
begin |
wb_strobe<=1'b1; |
wb_addr<={pcx_req_d,19'b0,pcx_packet_d[103:64+5],5'b11000}; |
wb_sel<=8'b11111111; // It is always full width for subsequent accesses |
state<=`PCX_REQ_STEP4_1; |
end |
`PCX_REQ_STEP4_1: |
if(wb_ack==1) |
begin |
wb_cycle<=0; |
wb_strobe<=0; |
wb_sel<=8'b0; |
wb_addr<=64'b0; |
wb_we<=0; |
cpx_packet_2[63:0]<=wb_data_i; |
state<=`CPX_READY_1; |
end |
`PCX_BIS: // Block init store |
begin |
wb_strobe<=1'b1; |
wb_we<=1; |
wb_addr<={pcx_req_d,19'b0,pcx_packet_d[103:64+6],6'b001000}; |
wb_sel<=8'b11111111; |
wb_data_o<=64'b0; |
state<=`PCX_BIS_1; |
end |
`PCX_BIS_1: |
if(wb_ack) |
begin |
wb_strobe<=0; |
if(wb_addr[39:0]<(pcx_packet_d[64+39:64]+8*7)) |
state<=`PCX_BIS_2; |
else |
begin |
wb_cycle<=0; |
wb_sel<=0; |
wb_we<=0; |
wb_addr<=64'b0; |
state<=`CPX_READY_1; |
end |
end |
`PCX_BIS_2: |
begin |
wb_strobe<=1'b1; |
wb_addr[5:0]<=wb_addr[5:0]+8; |
state<=`PCX_BIS_1; |
end |
`PCX_FP_1: |
begin |
fp_pcx<=pcx_packet_d; |
fp_req<=1; |
state<=`PCX_FP_2; |
if(`DEBUGGING) |
begin |
wb_addr<=pcx_packet_d[103:64]; |
wb_data_o<=pcx_packet_d[63:0]; |
wb_sel<=8'h22; |
end |
end |
`PCX_FP_2: |
begin |
fp_pcx<=pcx_packet_2nd; |
state<=`FP_WAIT; |
if(`DEBUGGING) |
begin |
wb_addr<=pcx_packet_2nd[103:64]; |
wb_data_o<=pcx_packet_d[63:0]; |
wb_sel<=8'h23; |
end |
end |
`FP_WAIT: |
begin |
fp_pcx<=124'b0; |
fp_req<=0; |
if(fp_rdy) |
state<=`CPX_FP; |
if(`DEBUGGING) |
wb_sel<=8'h24; |
end |
`CPX_FP: |
if(fp_cpx[144]) // Packet valid |
begin |
cpx_packet_1<=fp_cpx; |
state<=`CPX_READY_1; |
if(`DEBUGGING) |
begin |
wb_addr<=fp_cpx[63:0]; |
wb_data_o<=fp_cpx[127:64]; |
end |
end |
else |
if(!fp_rdy) |
state<=`FP_WAIT; // Else wait for another one if it is not here still |
`CPX_SEND_ETH_IRQ: |
begin |
cpx_packet_1<=145'h1_7_000_000000000000001D_000000000000_001D; |
eth_int_sent<=0; |
state<=`CPX_READY_1; |
end |
`CPX_INT_VEC_DIS: |
begin |
if(pcx_packet_d[12:10]==3'b000) |
cpx_two_packet<=1; // Send interrupt only if it is for this core |
cpx_packet_1[144:140]<=5'b10100; |
cpx_packet_1[139:137]<=0; |
cpx_packet_1[136]<=1; |
cpx_packet_1[135:134]<=pcx_packet_d[113:112]; // Thread ID |
cpx_packet_1[133:130]<=0; |
cpx_packet_1[129]<=pcx_atom_d; |
cpx_packet_1[128]<=0; |
cpx_packet_1[127:0]<={5'b0,pcx_packet_d[64+5:64+4],3'b0,pcx_packet_d[64+11:64+6],112'b0}; |
cpx_packet_2<={9'h170,54'h0,pcx_packet_d[17:0],46'h0,pcx_packet_d[17:0]}; |
state<=`CPX_READY_1; |
end |
`CPX_READY_1: |
begin |
cpx_ready<=1; |
cpx_packet<=cpx_packet_1; |
cnt<=cnt+1; |
if(`DEBUGGING) |
if(multi_hit || multi_hit1) |
wb_sel<=8'h11; |
if(!cpx_two_packet) |
state<=`PCX_IDLE; |
else |
//if(cnt==4'b1111 || pcx_packet_d[103:64]!=40'h9800000800) |
state<=`CPX_READY_2; |
end |
`CPX_READY_2: |
begin |
cpx_ready<=1; |
cpx_packet<=cpx_packet_2; |
state<=`PCX_IDLE; |
end |
`PCX_UNKNOWN: |
begin |
wb_sel<=8'b10100101; // Illegal eye-catching value for debugging |
state<=`PCX_IDLE; |
end |
endcase |
|
l1dir l1dir_inst( |
.clk(clk), |
.reset(!rstn), |
|
.cpu(0), // Issuing CPU number |
.strobe(state==`GOT_PCX_REQ), |
.way(pcx_packet[108:107]), // Way to allocate for allocating loads |
.address(pcx_packet[64+39:64]), |
.load(pcx_packet[122:118]==5'b00000), |
.ifill(pcx_packet[122:118]==5'b10000), |
.store(pcx_packet[122:118]==5'b00001), |
.cas(pcx_packet[122:118]==5'b00010), |
.swap(pcx_packet[122:118]==5'b00110), |
.strload(pcx_packet[122:118]==5'b00100), |
.strstore(pcx_packet[122:118]==5'b00101), |
.cacheable((!pcx_packet[117]) && (!pcx_req_d[4])), |
.prefetch(pcx_packet[110]), |
.invalidate(pcx_packet[111]), |
.blockstore(pcx_packet[109] | pcx_packet[110]), |
|
.inval_vect0(inval_vect0), // Invalidation vector |
.inval_vect1(inval_vect1), |
.othercachehit(othercachehit), // Other cache hit in the same CPU, wayval0/wayval1 |
.othercpuhit(othercpuhit), // Any cache hit in the other CPU, wayval0/wayval1 |
.wayval0(wayval0), // Way valid |
.wayval1(wayval1), // Second way valid for ifill |
.ready(ready), // Directory init done |
); |
|
endmodule |
`timescale 1ns / 1ps |
////////////////////////////////////////////////////////////////////////////////// |
// Company: (C) Athree, 2009 |
// Engineer: Dmitry Rozhdestvenskiy |
// Email dmitry.rozhdestvenskiy@srisc.com dmitryr@a3.spb.ru divx4log@narod.ru |
// |
// Design Name: Bridge from SPARC Core to Wishbone Master |
// Module Name: os2wb |
// Project Name: SPARC SoC single-core |
// |
// LICENSE: |
// This is a Free Hardware Design; you can redistribute it and/or |
// modify it under the terms of the GNU General Public License |
// version 2 as published by the Free Software Foundation. |
// The above named program 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 General Public License for more details. |
// |
////////////////////////////////////////////////////////////////////////////////// |
module os2wb_dual( |
input clk, |
input rstn, |
|
// Core interface |
input [ 4:0] pcx_req, |
input pcx_atom, |
input [123:0] pcx_data, |
output reg [ 4:0] pcx_grant, |
output reg cpx_ready, |
output reg [144:0] cpx_packet, |
|
// Core 2nd interface |
input [ 4:0] pcx1_req, |
input pcx1_atom, |
input [123:0] pcx1_data, |
output reg [ 4:0] pcx1_grant, |
output reg cpx1_ready, |
output reg [144:0] cpx1_packet, |
|
// Wishbone master interface |
input [ 63:0] wb_data_i, |
input wb_ack, |
output reg wb_cycle, |
output reg wb_strobe, |
output reg wb_we, |
output reg [ 7:0] wb_sel, |
output reg [ 63:0] wb_addr, |
output reg [ 63:0] wb_data_o, |
|
// FPU interface |
output reg [123:0] fp_pcx, |
output reg fp_req, |
input [144:0] fp_cpx, |
input fp_rdy, |
|
// Ethernet interrupt, sensed on posedge, mapped to vector 'd29 |
input eth_int |
); |
|
reg [123:0] pcx_packet_d; // Latched incoming PCX packet |
reg [123:0] pcx_packet_2nd; // Second packet for atomic (CAS) |
reg [ 4:0] pcx_req_d; // Latched request |
reg pcx_atom_d; // Latched atomic flasg |
reg [ 4:0] state; // FSM state |
reg [144:0] cpx_packet_1; // First CPX packet |
reg [144:0] cpx_packet_2; // Second CPX packet (for atomics and cached IFILLs) |
reg cpx_two_packet; // CPX answer is two-packet (!=atomic, SWAP has atomic==0 and answer is two-packet) |
|
wire [111:0] inval_vect0; // Invalidate, instr/data, way |
wire [111:0] inval_vect1; // IFill may cause two D lines invalidation at a time |
|
wire [1:0] othercachehit; |
wire [1:0] othercpuhit; |
wire [1:0] wayval0; |
wire [1:0] wayval1; |
|
`define TEST_DRAM_1 5'b00000 |
`define TEST_DRAM_2 5'b00001 |
`define TEST_DRAM_3 5'b00010 |
`define TEST_DRAM_4 5'b00011 |
`define INIT_DRAM_1 5'b00100 |
`define INIT_DRAM_2 5'b00101 |
`define WAKEUP 5'b00110 |
`define PCX_IDLE 5'b00111 |
`define GOT_PCX_REQ 5'b01000 |
`define PCX_REQ_2ND 5'b01001 |
`define PCX_REQ_STEP1 5'b01010 |
`define PCX_REQ_STEP1_1 5'b01011 |
`define PCX_REQ_STEP2 5'b01100 |
`define PCX_REQ_STEP2_1 5'b01101 |
`define PCX_REQ_STEP3 5'b01110 |
`define PCX_REQ_STEP3_1 5'b01111 |
`define PCX_REQ_STEP4 5'b10000 |
`define PCX_REQ_STEP4_1 5'b10001 |
`define PCX_BIS 5'b10010 |
`define PCX_BIS_1 5'b10011 |
`define PCX_BIS_2 5'b10100 |
`define CPX_READY_1 5'b10101 |
`define CPX_READY_2 5'b10110 |
`define PCX_REQ_STEP1_2 5'b10111 |
`define PCX_UNKNOWN 5'b11000 |
`define PCX_FP_1 5'b11001 |
`define PCX_FP_2 5'b11010 |
`define FP_WAIT 5'b11011 |
`define CPX_FP 5'b11100 |
`define CPX_SEND_ETH_IRQ 5'b11101 |
`define CPX_INT_VEC_DIS 5'b11110 |
`define PCX_REQ_CAS_COMPARE 5'b11111 |
|
`define MEM_SIZE 64'h00000000_10000000 |
|
`define TEST_DRAM 1 |
`define DEBUGGING 1 |
|
reg cache_init; |
wire [3:0] dcache0_hit; |
wire [3:0] dcache1_hit; |
wire [3:0] icache_hit; |
reg multi_hit; |
reg multi_hit1; |
reg eth_int_d; |
reg eth_int_send; |
reg eth_int_sent; |
reg [3:0] cnt; |
|
// PCX channel FIFO |
wire [129:0] pcx_data_fifo; |
wire pcx_fifo_empty; |
reg [ 4:0] pcx_req_1; |
reg [ 4:0] pcx_req_2; |
reg pcx_atom_1; |
reg pcx_atom_2; |
reg pcx_data_123_d; |
|
// PCX 2nf channel FIFO |
wire [129:0] pcx1_data_fifo; |
wire pcx1_fifo_empty; |
reg [ 4:0] pcx1_req_1; |
reg [ 4:0] pcx1_req_2; |
reg pcx1_atom_1; |
reg pcx1_atom_2; |
reg pcx1_data_123_d; |
|
always @(posedge clk) |
begin |
pcx_req_1<=pcx_req; |
pcx_atom_1<=pcx_atom; |
pcx_atom_2<=pcx_atom_1; |
pcx_req_2<=pcx_atom_1 ? pcx_req_1:5'b0; |
pcx_grant<=(pcx_req_1 | pcx_req_2); |
pcx_data_123_d<=pcx_data[123]; |
|
pcx1_req_1<=pcx1_req; |
pcx1_atom_1<=pcx1_atom; |
pcx1_atom_2<=pcx1_atom_1; |
pcx1_req_2<=pcx1_atom_1 ? pcx1_req_1:5'b0; |
pcx1_grant<=(pcx1_req_1 | pcx1_req_2); |
pcx1_data_123_d<=pcx1_data[123]; |
end |
|
pcx_fifo pcx_fifo_inst( |
// FIFO should be first word fall-through |
// It has no full flag as the core will send only limited number of requests, |
// in original design we used it 32 words deep |
// Just make it deeper if you experience overflow - |
// you can't just send no grant on full because the core expects immediate |
// grant for at least two requests for each zone |
.aclr(!rstn), |
.clock(clk), |
.data({pcx_atom_1,pcx_req_1,pcx_data}), |
.rdreq(fifo_rd), |
.wrreq((pcx_req_1!=5'b00000 && pcx_data[123]) || (pcx_atom_2 && pcx_data_123_d)), |
// Second atomic packet for FPU may be invalid, but should be sent to FPU |
// so if the first atomic packet is valid we latch both |
.empty(pcx_fifo_empty), |
.q(pcx_data_fifo) |
); |
|
pcx_fifo pcx_fifo_inst1( |
// FIFO should be first word fall-through |
// It has no full flag as the core will send only limited number of requests, |
// in original design we used it 32 words deep |
// Just make it deeper if you experience overflow - |
// you can't just send no grant on full because the core expects immediate |
// grant for at least two requests for each zone |
.aclr(!rstn), |
.clock(clk), |
.data({pcx1_atom_1,pcx1_req_1,pcx1_data}), |
.rdreq(fifo_rd1), |
.wrreq((pcx1_req_1!=5'b00000 && pcx1_data[123]) || (pcx1_atom_2 && pcx1_data_123_d)), |
// Second atomic packet for FPU may be invalid, but should be sent to FPU |
// so if the first atomic packet is valid we latch both |
.empty(pcx1_fifo_empty), |
.q(pcx1_data_fifo) |
); |
// -------------------------- |
|
reg wb_ack_d; |
|
always @(posedge clk or negedge rstn) |
if(!rstn) |
eth_int_send<=0; |
else |
begin |
wb_ack_d<=wb_ack; |
eth_int_d<=eth_int; |
if(eth_int && !eth_int_d) |
eth_int_send<=1; |
else |
if(eth_int_sent) |
eth_int_send<=0; |
end |
|
reg fifo_rd; |
reg fifo_rd1; |
wire [123:0] pcx_packet; |
assign pcx_packet=cpu ? pcx1_data_fifo[123:0]:pcx_data_fifo[123:0]; |
reg cpu; |
reg cpu2; |
|
always @(posedge clk or negedge rstn) |
if(rstn==0) |
begin |
if(`TEST_DRAM) |
state<=`TEST_DRAM_1; |
else |
state<=`INIT_DRAM_1; // DRAM initialization is mandatory! |
cpx_ready<=0; |
fifo_rd<=0; |
cpx_packet<=145'b0; |
wb_cycle<=0; |
wb_strobe<=0; |
wb_we<=0; |
wb_sel<=0; |
wb_addr<=64'b0; |
wb_data_o<=64'b0; |
pcx_packet_d<=124'b0; |
fp_pcx<=124'b0; |
fp_req<=0; |
end |
else |
case(state) |
`TEST_DRAM_1: |
begin |
wb_cycle<=1; |
wb_strobe<=1; |
wb_sel<=8'hFF; |
wb_we<=1; |
state<=`TEST_DRAM_2; |
end |
`TEST_DRAM_2: |
if(wb_ack) |
begin |
wb_strobe<=0; |
if(wb_addr<`MEM_SIZE-8) |
begin |
wb_addr[31:0]<=wb_addr[31:0]+8; |
wb_data_o<={wb_addr[31:0]+8,wb_addr[31:0]+8}; |
state<=`TEST_DRAM_1; |
end |
else |
begin |
state<=`TEST_DRAM_3; |
wb_cycle<=0; |
wb_sel<=0; |
wb_we<=0; |
wb_data_o<=64'b0; |
wb_addr<=64'b0; |
end |
end |
`TEST_DRAM_3: |
begin |
wb_cycle<=1; |
wb_strobe<=1; |
wb_sel<=8'hFF; |
state<=`TEST_DRAM_4; |
end |
`TEST_DRAM_4: |
if(wb_ack) |
begin |
wb_strobe<=0; |
if(wb_addr<`MEM_SIZE-8) |
begin |
if(wb_data_i=={wb_addr[31:0],wb_addr[31:0]}) |
begin |
wb_addr[31:0]<=wb_addr[31:0]+8; |
state<=`TEST_DRAM_3; |
end |
end |
else |
begin |
state<=`INIT_DRAM_1; |
wb_cycle<=0; |
wb_sel<=0; |
wb_we<=0; |
wb_data_o<=64'b0; |
wb_addr<=64'b0; |
end |
end |
`INIT_DRAM_1: |
begin |
wb_cycle<=1; |
wb_strobe<=1; |
wb_sel<=8'hFF; |
wb_we<=1; |
cache_init<=1; // We also init cache directories here |
state<=`INIT_DRAM_2; |
end |
`INIT_DRAM_2: |
if(wb_ack) |
begin |
wb_strobe<=0; |
if(wb_addr<`MEM_SIZE-8) |
begin |
wb_addr[31:0]<=wb_addr[31:0]+8; |
pcx_packet_d[64+11:64+4]<=pcx_packet_d[64+11:64+4]+1; // Address for cachedir init |
state<=`INIT_DRAM_1; |
end |
else |
begin |
state<=`WAKEUP; |
wb_cycle<=0; |
wb_sel<=0; |
wb_we<=0; |
cache_init<=0; |
wb_addr<=64'b0; |
end |
end |
`WAKEUP: |
begin |
cpx_packet<=145'h1700000000000000000000000000000010001; |
cpx_ready<=1; |
state<=`PCX_IDLE; |
end |
`PCX_IDLE: |
begin |
cnt<=0; |
cpx_packet<=145'b0; |
cpx_ready<=0; |
cpx1_packet<=145'b0; |
cpx1_ready<=0; |
cpx_two_packet<=0; |
multi_hit<=0; |
multi_hit1<=0; |
if(eth_int_send) |
begin |
state<=`CPX_SEND_ETH_IRQ; |
eth_int_sent<=1; |
end |
else |
if(!pcx_fifo_empty) |
begin |
pcx_req_d<=pcx_data_fifo[128:124]; |
pcx_atom_d<=pcx_data_fifo[129]; |
fifo_rd<=1; |
state<=`GOT_PCX_REQ; |
cpu<=0; |
cpu2<=0; |
end |
else |
if(!pcx1_fifo_empty) |
begin |
pcx_req_d<=pcx1_data_fifo[128:124]; |
pcx_atom_d<=pcx1_data_fifo[129]; |
fifo_rd1<=1; |
state<=`GOT_PCX_REQ; |
cpu<=1; |
cpu2<=1; |
end |
end |
`GOT_PCX_REQ: |
begin |
pcx_packet_d<=pcx_packet; |
if(`DEBUGGING) |
begin |
wb_sel[1:0]<=pcx_packet[113:112]; |
wb_sel[2]<=1; |
end |
if(pcx_packet[103:64]==40'h9800000800 && pcx_packet[122:118]==5'b00001) |
begin |
state<=`CPX_INT_VEC_DIS; |
fifo_rd<=0; |
fifo_rd1<=0; |
end |
else |
if(pcx_atom_d==0) |
begin |
fifo_rd<=0; |
fifo_rd1<=0; |
if(pcx_packet[122:118]==5'b01010) // FP req |
begin |
state<=`PCX_FP_1; |
pcx_packet_2nd[123]<=0; |
end |
else |
state<=`PCX_REQ_STEP1; |
end |
else |
state<=`PCX_REQ_2ND; |
end |
`PCX_REQ_2ND: |
begin |
pcx_packet_2nd<=pcx_packet; //Latch second packet for atomics |
if(`DEBUGGING) |
if(pcx_fifo_empty) |
wb_sel<=8'h67; |
fifo_rd<=0; |
fifo_rd1<=0; |
if(pcx_packet_d[122:118]==5'b01010) // FP req |
state<=`PCX_FP_1; |
else |
state<=`PCX_REQ_STEP1; |
end |
`PCX_REQ_STEP1: |
begin |
if(pcx_packet_d[111]==1'b1) // Invalidate request |
begin |
cpx_packet_1[144]<=1; // Valid |
cpx_packet_1[143:140]<=4'b0100; // Invalidate reply is Store ACK |
cpx_packet_1[139]<=1; // L2 miss |
cpx_packet_1[138:137]<=0; // Error |
cpx_packet_1[136]<=pcx_packet_d[117]; // Non-cacheble |
cpx_packet_1[135:134]<=pcx_packet_d[113:112]; // Thread ID |
cpx_packet_1[133:131]<=0; // Way valid |
cpx_packet_1[130]<=((pcx_packet_d[122:118]==5'b10000) && (pcx_req_d==5'b10000)) ? 1:0; // Four byte fill |
cpx_packet_1[129]<=pcx_atom_d; |
cpx_packet_1[128]<=pcx_packet_d[110]; // Prefetch |
cpx_packet_1[127:0]<={2'b0,pcx_packet_d[109]/*BIS*/,pcx_packet_d[122:118]==5'b00000 ? 2'b01:2'b10,pcx_packet_d[64+5:64+4],2'b0,cpu,pcx_packet_d[64+11:64+6],112'b0}; |
state<=`CPX_READY_1; |
end |
else |
if(pcx_packet_d[122:118]!=5'b01001) // Not INT |
begin |
wb_cycle<=1'b1; |
wb_strobe<=1'b1; |
if((pcx_packet_d[122:118]==5'b00000 && !pcx_req_d[4]) || pcx_packet_d[122:118]==5'b00010 || pcx_packet_d[122:118]==5'b00100 || pcx_packet_d[122:118]==5'b00110) |
wb_addr<={pcx_req_d,19'b0,pcx_packet_d[103:64+4],4'b0000}; //DRAM load/streamload, CAS and SWAP always use DRAM and load first |
else |
if(pcx_packet_d[122:118]==5'b10000 && !pcx_req_d[4]) |
wb_addr<={pcx_req_d,19'b0,pcx_packet_d[103:64+5],5'b00000}; //DRAM ifill |
else |
if(pcx_packet_d[64+39:64+28]==12'hFFF && pcx_packet_d[64+27:64+24]!=4'b0) // flash remap FFF1->FFF8 |
wb_addr<={pcx_req_d,19'b0,pcx_packet_d[103:64+3]+37'h0000E00000,3'b000}; |
else |
wb_addr<={pcx_req_d,19'b0,pcx_packet_d[103:64+3],3'b000}; |
wb_data_o<=pcx_packet_d[63:0]; |
state<=`PCX_REQ_STEP1_1; |
end |
else |
//if((pcx_packet_d[12:10]!=3'b000) && !pcx_packet_d[117]) // Not FLUSH int and not this core |
// state<=`PCX_IDLE; |
//else |
state<=`CPX_READY_1; |
case(pcx_packet_d[122:118]) // Packet type |
5'b00000://Load |
begin |
wb_we<=0; |
if(!pcx_req_d[4]) |
wb_sel<=8'b11111111; // DRAM requests are always 128 bit |
else |
case(pcx_packet_d[106:104]) //Size |
3'b000://Byte |
case(pcx_packet_d[64+2:64]) |
3'b000:wb_sel<=8'b10000000; |
3'b001:wb_sel<=8'b01000000; |
3'b010:wb_sel<=8'b00100000; |
3'b011:wb_sel<=8'b00010000; |
3'b100:wb_sel<=8'b00001000; |
3'b101:wb_sel<=8'b00000100; |
3'b110:wb_sel<=8'b00000010; |
3'b111:wb_sel<=8'b00000001; |
endcase |
3'b001://Halfword |
case(pcx_packet_d[64+2:64+1]) |
2'b00:wb_sel<=8'b11000000; |
2'b01:wb_sel<=8'b00110000; |
2'b10:wb_sel<=8'b00001100; |
2'b11:wb_sel<=8'b00000011; |
endcase |
3'b010://Word |
wb_sel<=(pcx_packet_d[64+2]==0) ? 8'b11110000:8'b00001111; |
3'b011://Doubleword |
wb_sel<=8'b11111111; |
3'b100://Quadword |
wb_sel<=8'b11111111; |
3'b111://Cacheline |
wb_sel<=8'b11111111; |
default: |
wb_sel<=8'b01011010; // Unreal eye-catching value for debug |
endcase |
end |
5'b00001://Store |
begin |
wb_we<=1; |
if(pcx_packet_d[110:109]!=2'b00) //Block (or init) store |
wb_sel<=8'b11111111; // Blocks are always 64 bit |
else |
case(pcx_packet_d[106:104]) //Size |
3'b000://Byte |
case(pcx_packet_d[64+2:64]) |
3'b000:wb_sel<=8'b10000000; |
3'b001:wb_sel<=8'b01000000; |
3'b010:wb_sel<=8'b00100000; |
3'b011:wb_sel<=8'b00010000; |
3'b100:wb_sel<=8'b00001000; |
3'b101:wb_sel<=8'b00000100; |
3'b110:wb_sel<=8'b00000010; |
3'b111:wb_sel<=8'b00000001; |
endcase |
3'b001://Halfword |
case(pcx_packet_d[64+2:64+1]) |
2'b00:wb_sel<=8'b11000000; |
2'b01:wb_sel<=8'b00110000; |
2'b10:wb_sel<=8'b00001100; |
2'b11:wb_sel<=8'b00000011; |
endcase |
3'b010://Word |
wb_sel<=(pcx_packet_d[64+2]==0) ? 8'b11110000:8'b00001111; |
3'b011://Doubleword |
wb_sel<=8'b11111111; |
default: |
if(`DEBUGGING) |
wb_sel<=8'b01011010; // Unreal eye-catching value for debug |
endcase |
end |
5'b00010://CAS |
begin |
wb_we<=0; //Load first |
wb_sel<=8'b11111111; // CAS loads are as cacheline |
end |
5'b00100://STRLOAD |
begin |
wb_we<=0; |
wb_sel<=8'b11111111; // Stream loads are always 128 bit |
end |
5'b00101://STRSTORE |
begin |
wb_we<=1; |
case(pcx_packet_d[106:104]) //Size |
3'b000://Byte |
case(pcx_packet_d[64+2:64]) |
3'b000:wb_sel<=8'b10000000; |
3'b001:wb_sel<=8'b01000000; |
3'b010:wb_sel<=8'b00100000; |
3'b011:wb_sel<=8'b00010000; |
3'b100:wb_sel<=8'b00001000; |
3'b101:wb_sel<=8'b00000100; |
3'b110:wb_sel<=8'b00000010; |
3'b111:wb_sel<=8'b00000001; |
endcase |
3'b001://Halfword |
case(pcx_packet_d[64+2:64+1]) |
2'b00:wb_sel<=8'b11000000; |
2'b01:wb_sel<=8'b00110000; |
2'b10:wb_sel<=8'b00001100; |
2'b11:wb_sel<=8'b00000011; |
endcase |
3'b010://Word |
wb_sel<=(pcx_packet_d[64+2]==0) ? 8'b11110000:8'b00001111; |
3'b011://Doubleword |
wb_sel<=8'b11111111; |
3'b100://Quadword |
wb_sel<=8'b11111111; |
3'b111://Cacheline |
wb_sel<=8'b11111111; |
default: |
wb_sel<=8'b01011010; // Unreal eye-catching value for debug |
endcase |
end |
5'b00110://SWAP/LDSTUB |
begin |
wb_we<=0; // Load first, as CAS |
wb_sel<=8'b11111111; // SWAP/LDSTUB loads are as cacheline |
end |
5'b01001://INT |
if(pcx_packet_d[117]) // Flush |
begin |
cpx_packet_1<={9'h171,pcx_packet_d[113:112],11'h0,pcx_packet_d[64+5:64+4],2'b0,cpu,pcx_packet_d[64+11:64+6],30'h0,pcx_packet_d[17:0],46'b0,pcx_packet_d[17:0]}; //FLUSH instruction answer |
cpx_packet_2<={9'h171,pcx_packet_d[113:112],11'h0,pcx_packet_d[64+5:64+4],2'b0,cpu,pcx_packet_d[64+11:64+6],30'h0,pcx_packet_d[17:0],46'b0,pcx_packet_d[17:0]}; //FLUSH instruction answer |
cpx_two_packet<=1; |
cpu2<=!cpu; // Flush should be sent to both cores |
end |
else // Tread-to-thread interrupt |
begin |
cpx_packet_1<={9'h170,pcx_packet_d[113:112],52'h0,pcx_packet_d[17:0],46'h0,pcx_packet_d[17:0]}; |
cpu<=pcx_packet_d[10]; |
end |
//5'b01010: FP1 - processed by separate state |
//5'b01011: FP2 - processed by separate state |
//5'b01101: FWDREQ - not implemented |
//5'b01110: FWDREPL - not implemented |
5'b10000://IFILL |
begin |
wb_we<=0; |
if(pcx_req_d[4]) // I/O access |
wb_sel<=(pcx_packet_d[64+2]==0) ? 8'b11110000:8'b00001111; |
else |
wb_sel<=8'b11111111; |
end |
default: |
begin |
wb_we<=0; |
wb_sel<=8'b10101010; // Unreal eye-catching value for debug |
end |
endcase |
end |
`PCX_REQ_STEP1_1: |
state<=`PCX_REQ_STEP1_2; // Delay for L1 directory |
`PCX_REQ_STEP1_2: |
begin |
if(wb_ack || wb_ack_d) |
begin |
cpx_packet_1[144]<=1; // Valid |
cpx_packet_1[139]<=(pcx_packet_d[122:118]==5'b00000) || (pcx_packet_d[122:118]==5'b10000) ? 1:0; // L2 always miss on load and ifill |
cpx_packet_1[138:137]<=0; // Error |
cpx_packet_1[136]<=pcx_packet_d[117] || (pcx_packet_d[122:118]==5'b00001) ? 1:0; // Non-cacheble is set on store too |
cpx_packet_1[135:134]<=pcx_packet_d[113:112]; // Thread ID |
if((pcx_packet_d[122:118]==5'b00000 && !pcx_packet_d[117] && !pcx_packet_d[110]) || (pcx_packet_d[122:118]==5'b10000)) // Cacheble Load or IFill |
cpx_packet_1[133:131]<={othercachehit[0],wayval0}; |
else |
cpx_packet_1[133:131]<=3'b000; // Way valid |
if(pcx_packet_d[122:118]==5'b00100) // Strload |
cpx_packet_1[130]<=pcx_packet_d[106]; // A |
else |
if(pcx_packet_d[122:118]==5'b00101) // Stream store |
cpx_packet_1[130]<=pcx_packet_d[108]; // A |
else |
cpx_packet_1[130]<=((pcx_packet_d[122:118]==5'b10000) && pcx_req_d[4]) ? 1:0; // Four byte fill |
if(pcx_packet_d[122:118]==5'b00100) // Strload |
cpx_packet_1[129]<=pcx_packet_d[105]; // B |
else |
cpx_packet_1[129]<=pcx_atom_d || (pcx_packet_d[122:118]==5'b00110); // SWAP is single-packet but needs atom in CPX |
cpx_packet_1[128]<=pcx_packet_d[110] && pcx_packet_d[122:118]==5'b00000; // Prefetch |
cpx_packet_2[144]<=1; // Valid |
cpx_packet_2[139]<=0; // L2 miss |
cpx_packet_2[138:137]<=0; // Error |
cpx_packet_2[136]<=pcx_packet_d[117] || (pcx_packet_d[122:118]==5'b00001) ? 1:0; // Non-cacheble is set on store too |
cpx_packet_2[135:134]<=pcx_packet_d[113:112]; // Thread ID |
if(pcx_packet_d[122:118]==5'b10000) // IFill |
cpx_packet_2[133:131]<={othercachehit[1],wayval1}; |
else |
cpx_packet_2[133:131]<=3'b000; // Way valid |
cpx_packet_2[130]<=0; // Four byte fill |
cpx_packet_2[129]<=pcx_atom_d || (pcx_packet_d[122:118]==5'b00110) || ((pcx_packet_d[122:118]==5'b10000) && !pcx_req_d[4]); |
cpx_packet_2[128]<=0; // Prefetch |
wb_strobe<=0; |
wb_sel<=8'b0; |
wb_addr<=64'b0; |
wb_data_o<=64'b0; |
wb_we<=0; |
case(pcx_packet_d[122:118]) // Packet type |
5'b00000://Load |
begin |
cpx_packet_1[143:140]<=4'b0000; // Type |
if(!pcx_req_d[4]) |
begin |
cpx_packet_1[127:0]<={wb_data_i,wb_data_i}; |
state<=`PCX_REQ_STEP2; |
end |
else |
case(pcx_packet_d[106:104]) //Size |
3'b000://Byte |
begin |
case(pcx_packet_d[64+2:64]) |
3'b000:cpx_packet_1[127:0]<={wb_data_i[63:56],wb_data_i[63:56],wb_data_i[63:56],wb_data_i[63:56],wb_data_i[63:56],wb_data_i[63:56],wb_data_i[63:56],wb_data_i[63:56],wb_data_i[63:56],wb_data_i[63:56],wb_data_i[63:56],wb_data_i[63:56],wb_data_i[63:56],wb_data_i[63:56],wb_data_i[63:56],wb_data_i[63:56]}; |
3'b001:cpx_packet_1[127:0]<={wb_data_i[55:48],wb_data_i[55:48],wb_data_i[55:48],wb_data_i[55:48],wb_data_i[55:48],wb_data_i[55:48],wb_data_i[55:48],wb_data_i[55:48],wb_data_i[55:48],wb_data_i[55:48],wb_data_i[55:48],wb_data_i[55:48],wb_data_i[55:48],wb_data_i[55:48],wb_data_i[55:48],wb_data_i[55:48]}; |
3'b010:cpx_packet_1[127:0]<={wb_data_i[47:40],wb_data_i[47:40],wb_data_i[47:40],wb_data_i[47:40],wb_data_i[47:40],wb_data_i[47:40],wb_data_i[47:40],wb_data_i[47:40],wb_data_i[47:40],wb_data_i[47:40],wb_data_i[47:40],wb_data_i[47:40],wb_data_i[47:40],wb_data_i[47:40],wb_data_i[47:40],wb_data_i[47:40]}; |
3'b011:cpx_packet_1[127:0]<={wb_data_i[39:32],wb_data_i[39:32],wb_data_i[39:32],wb_data_i[39:32],wb_data_i[39:32],wb_data_i[39:32],wb_data_i[39:32],wb_data_i[39:32],wb_data_i[39:32],wb_data_i[39:32],wb_data_i[39:32],wb_data_i[39:32],wb_data_i[39:32],wb_data_i[39:32],wb_data_i[39:32],wb_data_i[39:32]}; |
3'b100:cpx_packet_1[127:0]<={wb_data_i[31:24],wb_data_i[31:24],wb_data_i[31:24],wb_data_i[31:24],wb_data_i[31:24],wb_data_i[31:24],wb_data_i[31:24],wb_data_i[31:24],wb_data_i[31:24],wb_data_i[31:24],wb_data_i[31:24],wb_data_i[31:24],wb_data_i[31:24],wb_data_i[31:24],wb_data_i[31:24],wb_data_i[31:24]}; |
3'b101:cpx_packet_1[127:0]<={wb_data_i[23:16],wb_data_i[23:16],wb_data_i[23:16],wb_data_i[23:16],wb_data_i[23:16],wb_data_i[23:16],wb_data_i[23:16],wb_data_i[23:16],wb_data_i[23:16],wb_data_i[23:16],wb_data_i[23:16],wb_data_i[23:16],wb_data_i[23:16],wb_data_i[23:16],wb_data_i[23:16],wb_data_i[23:16]}; |
3'b110:cpx_packet_1[127:0]<={wb_data_i[15: 8],wb_data_i[15: 8],wb_data_i[15: 8],wb_data_i[15: 8],wb_data_i[15: 8],wb_data_i[15: 8],wb_data_i[15: 8],wb_data_i[15: 8],wb_data_i[15: 8],wb_data_i[15: 8],wb_data_i[15: 8],wb_data_i[15: 8],wb_data_i[15: 8],wb_data_i[15: 8],wb_data_i[15: 8],wb_data_i[15: 8]}; |
3'b111:cpx_packet_1[127:0]<={wb_data_i[ 7: 0],wb_data_i[ 7: 0],wb_data_i[ 7: 0],wb_data_i[ 7: 0],wb_data_i[ 7: 0],wb_data_i[ 7: 0],wb_data_i[ 7: 0],wb_data_i[ 7: 0],wb_data_i[ 7: 0],wb_data_i[ 7: 0],wb_data_i[ 7: 0],wb_data_i[ 7: 0],wb_data_i[ 7: 0],wb_data_i[ 7: 0],wb_data_i[ 7: 0],wb_data_i[ 7: 0]}; |
endcase |
wb_cycle<=0; |
state<=`CPX_READY_1; |
end |
3'b001://Halfword |
begin |
case(pcx_packet_d[64+2:64+1]) |
2'b00:cpx_packet_1[127:0]<={wb_data_i[63:48],wb_data_i[63:48],wb_data_i[63:48],wb_data_i[63:48],wb_data_i[63:48],wb_data_i[63:48],wb_data_i[63:48],wb_data_i[63:48]}; |
2'b01:cpx_packet_1[127:0]<={wb_data_i[47:32],wb_data_i[47:32],wb_data_i[47:32],wb_data_i[47:32],wb_data_i[47:32],wb_data_i[47:32],wb_data_i[47:32],wb_data_i[47:32]}; |
2'b10:cpx_packet_1[127:0]<={wb_data_i[31:16],wb_data_i[31:16],wb_data_i[31:16],wb_data_i[31:16],wb_data_i[31:16],wb_data_i[31:16],wb_data_i[31:16],wb_data_i[31:16]}; |
2'b11:cpx_packet_1[127:0]<={wb_data_i[15: 0],wb_data_i[15: 0],wb_data_i[15: 0],wb_data_i[15: 0],wb_data_i[15: 0],wb_data_i[15: 0],wb_data_i[15: 0],wb_data_i[15: 0]}; |
endcase |
wb_cycle<=0; |
state<=`CPX_READY_1; |
end |
3'b010://Word |
begin |
if(pcx_packet_d[64+2]==0) |
cpx_packet_1[127:0]<={wb_data_i[63:32],wb_data_i[63:32],wb_data_i[63:32],wb_data_i[63:32]}; |
else |
cpx_packet_1[127:0]<={wb_data_i[31:0],wb_data_i[31:0],wb_data_i[31:0],wb_data_i[31:0]}; |
wb_cycle<=0; |
state<=`CPX_READY_1; |
end |
3'b011://Doubleword |
begin |
cpx_packet_1[127:0]<={wb_data_i,wb_data_i}; |
wb_cycle<=0; |
state<=`CPX_READY_1; |
end |
3'b100://Quadword |
begin |
cpx_packet_1[127:0]<={wb_data_i,wb_data_i}; |
wb_cycle<=0; |
state<=`CPX_READY_1; // 16 byte access to PROM should just duplicate the data |
end |
3'b111://Cacheline |
begin |
cpx_packet_1[127:0]<={wb_data_i,wb_data_i}; |
wb_cycle<=0; |
state<=`CPX_READY_1; // 16 byte access to PROM should just duplicate the data |
end |
default: |
begin |
cpx_packet_1[127:0]<={wb_data_i,wb_data_i}; |
wb_cycle<=0; |
state<=`PCX_UNKNOWN; |
end |
endcase |
end |
5'b00001://Store |
begin |
cpx_packet_1[143:140]<=4'b0100; // Type |
cpx_packet_1[127:0]<={2'b0,pcx_packet_d[109]/*BIS*/,2'b0,pcx_packet_d[64+5:64+4],2'b0,cpu,pcx_packet_d[64+11:64+6],inval_vect0}; |
// if((pcx_packet_d[110:109]==2'b01) && (pcx_packet_d[64+5:64]==0) && !inval_vect0[3] && !inval_vect1[3]) // Block init store |
// state<=`PCX_BIS; |
// else |
// begin |
wb_cycle<=0; |
state<=`CPX_READY_1; |
// end |
end |
5'b00010://CAS |
begin |
cpx_packet_1[143:140]<=4'b0000; // Load return for first packet |
cpx_packet_2[143:140]<=4'b0100; // Store ACK for second packet |
cpx_packet_2[127:0]<={5'b0,pcx_packet_d[64+5:64+4],2'b0,cpu,pcx_packet_d[64+11:64+6],inval_vect0}; |
cpx_packet_1[127:0]<={wb_data_i,wb_data_i}; |
state<=`PCX_REQ_STEP2; |
end |
5'b00100://STRLOAD |
begin |
cpx_packet_1[143:140]<=4'b0010; // Type |
cpx_packet_1[127:0]<={wb_data_i,wb_data_i}; |
state<=`PCX_REQ_STEP2; |
end |
5'b00101://STRSTORE |
begin |
cpx_packet_1[143:140]<=4'b0110; // Type |
cpx_packet_1[127:0]<={5'b0,pcx_packet_d[64+5:64+4],3'b0,pcx_packet_d[64+11:64+6],inval_vect0}; |
wb_cycle<=0; |
state<=`CPX_READY_1; |
end |
5'b00110://SWAP/LDSTUB |
begin |
cpx_packet_1[143:140]<=4'b0000; // Load return for first packet |
cpx_packet_2[143:140]<=4'b0100; // Store ACK for second packet |
cpx_packet_2[127:0]<={5'b0,pcx_packet_d[64+5:64+4],3'b0,pcx_packet_d[64+11:64+6],inval_vect0}; |
cpx_packet_1[127:0]<={wb_data_i,wb_data_i}; |
state<=`PCX_REQ_STEP2; |
end |
5'b10000://IFILL |
begin |
cpx_packet_1[143:140]<=4'b0001; // Type |
cpx_packet_2[143:140]<=4'b0001; // Type |
if(pcx_req_d[4]) // I/O access |
begin |
if(pcx_packet_d[64+2]==0) |
cpx_packet_1[127:0]<={wb_data_i[63:32],wb_data_i[63:32],wb_data_i[63:32],wb_data_i[63:32]}; |
else |
cpx_packet_1[127:0]<={wb_data_i[31:0],wb_data_i[31:0],wb_data_i[31:0],wb_data_i[31:0]}; |
state<=`CPX_READY_1; |
wb_cycle<=0; |
end |
else |
begin |
cpx_packet_1[127:0]<={wb_data_i,wb_data_i}; |
state<=`PCX_REQ_STEP2; |
end |
end |
default: |
begin |
wb_cycle<=0; |
state<=`PCX_UNKNOWN; |
end |
endcase |
end |
end |
`PCX_REQ_STEP2: // IFill, Load/strload, CAS, SWAP, LDSTUB - alwas load |
begin |
wb_strobe<=1'b1; |
if(pcx_packet_d[122:118]==5'b10000) |
wb_addr<={pcx_req_d,19'b0,pcx_packet_d[103:64+5],5'b01000}; |
else |
wb_addr<={pcx_req_d,19'b0,pcx_packet_d[103:64+4],4'b1000}; |
wb_sel<=8'b11111111; // It is always full width for subsequent IFill and load accesses |
state<=`PCX_REQ_STEP2_1; |
end |
`PCX_REQ_STEP2_1: |
if(wb_ack==1) |
begin |
wb_strobe<=0; |
wb_sel<=8'b0; |
wb_addr<=64'b0; |
wb_data_o<=64'b0; |
wb_we<=0; |
cpx_packet_1[63:0]<=wb_data_i; |
if((pcx_packet_d[122:118]!=5'b00000) && (pcx_packet_d[122:118]!=5'b00100)) |
if(pcx_packet_d[122:118]!=5'b00010) // IFill, SWAP |
state<=`PCX_REQ_STEP3; |
else |
state<=`PCX_REQ_CAS_COMPARE; // CAS |
else |
begin |
wb_cycle<=0; |
state<=`CPX_READY_1; |
end |
end |
`PCX_REQ_CAS_COMPARE: |
begin |
cpx_two_packet<=1; |
if(pcx_packet_d[106:104]==3'b010) // 32-bit |
case(pcx_packet_d[64+3:64+2]) |
2'b00:state<=cpx_packet_1[127:96]==pcx_packet_d[63:32] ? `PCX_REQ_STEP3:`CPX_READY_1; |
2'b01:state<=cpx_packet_1[95:64]==pcx_packet_d[63:32] ? `PCX_REQ_STEP3:`CPX_READY_1; |
2'b10:state<=cpx_packet_1[63:32]==pcx_packet_d[63:32] ? `PCX_REQ_STEP3:`CPX_READY_1; |
2'b11:state<=cpx_packet_1[31:0]==pcx_packet_d[63:32] ? `PCX_REQ_STEP3:`CPX_READY_1; |
endcase |
else |
if(pcx_packet_d[64+3]==0) |
state<=cpx_packet_1[127:64]==pcx_packet_d[63:0] ? `PCX_REQ_STEP3:`CPX_READY_1; |
else |
state<=cpx_packet_1[63:0]==pcx_packet_d[63:0] ? `PCX_REQ_STEP3:`CPX_READY_1; |
end |
`PCX_REQ_STEP3: // 256-bit IFILL; CAS, SWAP and LDSTUB store |
begin |
if(pcx_packet_d[122:118]==5'b10000) |
wb_addr<={pcx_req_d,19'b0,pcx_packet_d[103:64+5],5'b10000}; |
else |
wb_addr<={pcx_req_d,19'b0,pcx_packet_d[103:64+3],3'b000}; // CAS or SWAP save |
cpx_two_packet<=1; |
if(pcx_packet_d[122:118]==5'b10000) |
wb_we<=0; |
else |
wb_we<=1; |
wb_strobe<=1'b1; |
if(pcx_packet_d[122:118]==5'b00010) // CAS |
if(pcx_packet_d[106:104]==3'b010) |
wb_sel<=(pcx_packet_d[64+2]==0) ? 8'b11110000:8'b00001111; |
else |
wb_sel<=8'b11111111; //CASX |
else |
if(pcx_packet_d[122:118]==5'b00110) //SWAP or LDSTUB |
if(pcx_packet_d[106:104]==3'b000) //LDSTUB |
case(pcx_packet_d[64+2:64]) |
3'b000:wb_sel<=8'b10000000; |
3'b001:wb_sel<=8'b01000000; |
3'b010:wb_sel<=8'b00100000; |
3'b011:wb_sel<=8'b00010000; |
3'b100:wb_sel<=8'b00001000; |
3'b101:wb_sel<=8'b00000100; |
3'b110:wb_sel<=8'b00000010; |
3'b111:wb_sel<=8'b00000001; |
endcase |
else |
wb_sel<=(pcx_packet_d[64+2]==0) ? 8'b11110000:8'b00001111; ///SWAP is always 32-bit |
else |
wb_sel<=8'b11111111; // It is always full width for subsequent IFill accesses |
if(pcx_packet_d[122:118]==5'b00110) //SWAP or LDSTUB |
wb_data_o<={pcx_packet_d[63:32],pcx_packet_d[63:32]}; |
// wb_data_o<=pcx_packet_d[63:0]; |
else |
wb_data_o<=pcx_packet_2nd[63:0]; // CAS store second packet data |
// if(pcx_packet_d[106:104]==3'b010) |
// wb_data_o<={pcx_packet_2nd[63:32],pcx_packet_2nd[63:32]}; // CAS store second packet data |
// else |
// wb_data_o<=pcx_packet_2nd[63:0]; |
state<=`PCX_REQ_STEP3_1; |
end |
`PCX_REQ_STEP3_1: |
if(wb_ack==1) |
begin |
wb_strobe<=0; |
wb_sel<=8'b0; |
wb_addr<=64'b0; |
wb_we<=0; |
wb_data_o<=64'b0; |
if(pcx_packet_d[122:118]==5'b10000) // IFill |
begin |
cpx_packet_2[127:64]<=wb_data_i; |
state<=`PCX_REQ_STEP4; |
end |
else |
begin |
wb_cycle<=0; |
state<=`CPX_READY_1; |
end |
end |
`PCX_REQ_STEP4: // 256-bit IFILL only |
begin |
wb_strobe<=1'b1; |
wb_addr<={pcx_req_d,19'b0,pcx_packet_d[103:64+5],5'b11000}; |
wb_sel<=8'b11111111; // It is always full width for subsequent accesses |
state<=`PCX_REQ_STEP4_1; |
end |
`PCX_REQ_STEP4_1: |
if(wb_ack==1) |
begin |
wb_cycle<=0; |
wb_strobe<=0; |
wb_sel<=8'b0; |
wb_addr<=64'b0; |
wb_we<=0; |
cpx_packet_2[63:0]<=wb_data_i; |
state<=`CPX_READY_1; |
end |
`PCX_BIS: // Block init store |
begin |
wb_strobe<=1'b1; |
wb_we<=1; |
wb_addr<={pcx_req_d,19'b0,pcx_packet_d[103:64+6],6'b001000}; |
wb_sel<=8'b11111111; |
wb_data_o<=64'b0; |
state<=`PCX_BIS_1; |
end |
`PCX_BIS_1: |
if(wb_ack) |
begin |
wb_strobe<=0; |
if(wb_addr[39:0]<(pcx_packet_d[64+39:64]+8*7)) |
state<=`PCX_BIS_2; |
else |
begin |
wb_cycle<=0; |
wb_sel<=0; |
wb_we<=0; |
wb_addr<=64'b0; |
state<=`CPX_READY_1; |
end |
end |
`PCX_BIS_2: |
begin |
wb_strobe<=1'b1; |
wb_addr[5:0]<=wb_addr[5:0]+8; |
state<=`PCX_BIS_1; |
end |
`PCX_FP_1: |
begin |
fp_pcx<=pcx_packet_d; |
fp_req<=1; |
state<=`PCX_FP_2; |
if(`DEBUGGING) |
begin |
wb_addr<=pcx_packet_d[103:64]; |
wb_data_o<=pcx_packet_d[63:0]; |
wb_sel<=8'h22; |
end |
end |
`PCX_FP_2: |
begin |
fp_pcx<=pcx_packet_2nd; |
state<=`FP_WAIT; |
if(`DEBUGGING) |
begin |
wb_addr<=pcx_packet_2nd[103:64]; |
wb_data_o<=pcx_packet_d[63:0]; |
wb_sel<=8'h23; |
end |
end |
`FP_WAIT: |
begin |
fp_pcx<=124'b0; |
fp_req<=0; |
if(fp_rdy) |
state<=`CPX_FP; |
if(`DEBUGGING) |
wb_sel<=8'h24; |
end |
`CPX_FP: |
if(fp_cpx[144]) // Packet valid |
begin |
cpx_packet_1<=fp_cpx; |
state<=`CPX_READY_1; |
if(`DEBUGGING) |
begin |
wb_addr<=fp_cpx[63:0]; |
wb_data_o<=fp_cpx[127:64]; |
end |
end |
else |
if(!fp_rdy) |
state<=`FP_WAIT; // Else wait for another one if it is not here still |
`CPX_SEND_ETH_IRQ: |
begin |
cpx_packet_1<=145'h1_7_000_000000000000001D_000000000000_001D; |
eth_int_sent<=0; |
state<=`CPX_READY_1; |
end |
`CPX_INT_VEC_DIS: |
begin |
//if(pcx_packet_d[12:10]==3'b000) // Send interrupt only if it is for this core |
cpx_two_packet<=1; |
cpu2<=pcx_packet_d[10]; |
cpx_packet_1[144:140]<=5'b10100; |
cpx_packet_1[139:137]<=0; |
cpx_packet_1[136]<=1; |
cpx_packet_1[135:134]<=pcx_packet_d[113:112]; // Thread ID |
cpx_packet_1[133:130]<=0; |
cpx_packet_1[129]<=pcx_atom_d; |
cpx_packet_1[128]<=0; |
cpx_packet_1[127:0]<={5'b0,pcx_packet_d[64+5:64+4],2'b0,cpu,pcx_packet_d[64+11:64+6],112'b0}; |
cpx_packet_2<={9'h170,54'h0,pcx_packet_d[17:0],46'h0,pcx_packet_d[17:0]}; |
state<=`CPX_READY_1; |
end |
`CPX_READY_1: |
begin |
if(!cpu) |
begin |
cpx_ready<=1; |
cpx_packet<=cpx_packet_1; |
if(othercpuhit[0]) |
begin |
cpx1_ready<=1; |
cpx1_packet<={1'b1,4'b0011,12'b0,5'b0,pcx_packet_d[64+5:64+4],3'b001,pcx_packet_d[64+11:64+6],inval_vect0}; |
end |
end |
else |
begin |
cpx1_ready<=1; |
cpx1_packet<=cpx_packet_1; |
if(othercpuhit[0]) |
begin |
cpx_ready<=1; |
cpx_packet<={1'b1,4'b0011,12'b0,5'b0,pcx_packet_d[64+5:64+4],3'b000,pcx_packet_d[64+11:64+6],inval_vect0};; |
end |
end |
cnt<=cnt+1; |
if(`DEBUGGING) |
if(multi_hit || multi_hit1) |
wb_sel<=8'h11; |
state<=`CPX_READY_2; |
end |
`CPX_READY_2: |
begin |
if(cpx_two_packet && !cpu2) |
begin |
cpx_ready<=1; |
cpx_packet<=cpx_packet_2; |
end |
else |
if(cpu2 && othercpuhit[1]) |
begin |
cpx_ready<=1; |
cpx_packet<={1'b1,4'b0011,12'b0,5'b0,pcx_packet_d[64+5:64+4],3'b000,pcx_packet_d[64+11:64+6],inval_vect1};; |
end |
else |
begin |
cpx_ready<=0; |
cpx_packet<=145'b0; |
end |
if(cpx_two_packet && cpu2) |
begin |
cpx1_ready<=1; |
cpx1_packet<=cpx_packet_2; |
end |
else |
if(!cpu2 && othercpuhit[1]) |
begin |
cpx1_ready<=1; |
cpx1_packet<={1'b1,4'b0011,12'b0,5'b0,pcx_packet_d[64+5:64+4],3'b001,pcx_packet_d[64+11:64+6],inval_vect1};; |
end |
else |
begin |
cpx1_ready<=0; |
cpx1_packet<=145'b0; |
end |
state<=`PCX_IDLE; |
end |
`PCX_UNKNOWN: |
begin |
wb_sel<=8'b10100101; // Illegal eye-catching value for debugging |
state<=`PCX_IDLE; |
end |
endcase |
|
l1dir l1dir_inst( |
.clk(clk), |
.reset(!rstn), |
|
.cpu(cpu), // Issuing CPU number |
.strobe(state==`GOT_PCX_REQ), |
.way(pcx_packet[108:107]), // Way to allocate for allocating loads |
.address(pcx_packet[64+39:64]), |
.load(pcx_packet[122:118]==5'b00000), |
.ifill(pcx_packet[122:118]==5'b10000), |
.store(pcx_packet[122:118]==5'b00001), |
.cas(pcx_packet[122:118]==5'b00010), |
.swap(pcx_packet[122:118]==5'b00110), |
.strload(pcx_packet[122:118]==5'b00100), |
.strstore(pcx_packet[122:118]==5'b00101), |
.cacheable((!pcx_packet[117]) && (!pcx_req_d[4])), |
.prefetch(pcx_packet[110]), |
.invalidate(pcx_packet[111]), |
.blockstore(pcx_packet[109] | pcx_packet[110]), |
|
.inval_vect0(inval_vect0), // Invalidation vector |
.inval_vect1(inval_vect1), |
.othercachehit(othercachehit), // Other cache hit in the same CPU, wayval0/wayval1 |
.othercpuhit(othercpuhit), // Any cache hit in the other CPU, wayval0/wayval1 |
.wayval0(wayval0), // Way valid |
.wayval1(wayval1), // Second way valid for ifill |
.ready(ready), // Directory init done |
); |
|
endmodule |
/os2wb/s1_top.v
24,18 → 24,18
*/ |
|
module s1_top ( |
input sys_clock_i, |
input sys_reset_i, |
|
input eth_irq_i, |
input sys_clock_i, |
input sys_reset_i, |
|
input wbm_ack_i, |
input eth_irq_i, |
|
input wbm_ack_i, |
input [63:0] wbm_data_i, |
output wbm_cycle_o, |
output wbm_strobe_o, |
output wbm_we_o, |
output [63:0] wbm_addr_o, |
output [63:0] wbm_data_o, |
output wbm_cycle_o, |
output wbm_strobe_o, |
output wbm_we_o, |
output [63:0] wbm_addr_o, |
output [63:0] wbm_data_o, |
output [ 7:0] wbm_sel_o |
); |
/* |
48,6 → 48,9
wire [4:0] spc_pcx_req_pq; // processor to pcx request |
wire spc_pcx_atom_pq; // processor to pcx atomic request |
wire [123:0] spc_pcx_data_pa; // processor to pcx packet |
wire [4:0] spc1_pcx_req_pq; // processor to pcx request |
wire spc1_pcx_atom_pq; // processor to pcx atomic request |
wire [123:0] spc1_pcx_data_pa; // processor to pcx packet |
|
// shadow scan |
wire spc_sscan_so; // From ifu of sparc_ifu.v |
68,8 → 71,12
wire [4:0] pcx_spc_grant_px; // pcx to processor grant info |
wire cpx_spc_data_rdy_cx2; // cpx data inflight to sparc |
wire [144:0] cpx_spc_data_cx2; // cpx to sparc data packet |
wire [4:0] pcx1_spc_grant_px; // pcx to processor grant info |
wire cpx1_spc_data_rdy_cx2; // cpx data inflight to sparc |
wire [144:0] cpx1_spc_data_cx2; // cpx to sparc data packet |
|
wire [3:0] const_cpuid; |
wire [3:0] const_cpuid1; |
wire [7:0] const_maskid; // To ifu of sparc_ifu.v |
|
// sscan |
120,7 → 127,8
/* |
* SPARC Core module instance |
*/ |
reg [ 4:0] pcx_spc_grant_px_fifo; |
reg [ 4:0] pcx_spc_grant_px_fifo; |
reg [ 4:0] pcx1_spc_grant_px_fifo; |
|
sparc sparc_0 ( |
|
171,67 → 179,124
.gdbginit_l(gdbginit_l) |
|
); |
|
|
|
sparc sparc_1 ( |
|
// Wires connected to SPARC Core outputs |
.spc_pcx_req_pq(spc1_pcx_req_pq), |
.spc_pcx_atom_pq(spc1_pcx_atom_pq), |
.spc_pcx_data_pa(spc1_pcx_data_pa), |
.spc_sscan_so(spc_sscan_so), |
.spc_scanout0(spc_scanout0), |
.spc_scanout1(spc_scanout1), |
.tst_ctu_mbist_done(tst_ctu_mbist_done), |
.tst_ctu_mbist_fail(tst_ctu_mbist_fail), |
.spc_efc_ifuse_data(spc_efc_ifuse_data), |
.spc_efc_dfuse_data(spc_efc_dfuse_data), |
|
// Wires connected to SPARC Core inputs |
.pcx_spc_grant_px(pcx1_spc_grant_px), |
.cpx_spc_data_rdy_cx2(cpx1_spc_data_rdy_cx2), |
.cpx_spc_data_cx2(cpx1_spc_data_cx2), |
.const_cpuid(const_cpuid1), |
.const_maskid(const_maskid), |
.ctu_tck(ctu_tck), |
.ctu_sscan_se(ctu_sscan_se), |
.ctu_sscan_snap(ctu_sscan_snap), |
.ctu_sscan_tid(ctu_sscan_tid), |
.ctu_tst_mbist_enable(ctu_tst_mbist_enable), |
.efc_spc_fuse_clk1(efc_spc_fuse_clk1), |
.efc_spc_fuse_clk2(efc_spc_fuse_clk2), |
.efc_spc_ifuse_ashift(efc_spc_ifuse_ashift), |
.efc_spc_ifuse_dshift(efc_spc_ifuse_dshift), |
.efc_spc_ifuse_data(efc_spc_ifuse_data), |
.efc_spc_dfuse_ashift(efc_spc_dfuse_ashift), |
.efc_spc_dfuse_dshift(efc_spc_dfuse_dshift), |
.efc_spc_dfuse_data(efc_spc_dfuse_data), |
.ctu_tst_macrotest(ctu_tst_macrotest), |
.ctu_tst_scan_disable(ctu_tst_scan_disable), |
.ctu_tst_short_chain(ctu_tst_short_chain), |
.global_shift_enable(global_shift_enable), |
.ctu_tst_scanmode(ctu_tst_scanmode), |
.spc_scanin0(spc_scanin0), |
.spc_scanin1(spc_scanin1), |
.cluster_cken(cluster_cken), |
.gclk(gclk), |
.cmp_grst_l(cmp_grst_l), |
.cmp_arst_l(cmp_arst_l), |
.ctu_tst_pre_grst_l(ctu_tst_pre_grst_l), |
.adbginit_l(adbginit_l), |
.gdbginit_l(gdbginit_l) |
|
); |
|
/* |
* SPARC Core to Wishbone Master bridge |
*/ |
|
wire fp_req; |
wire [123:0] fp_pcx; |
wire [ 7:0] fp_rdy; |
wire [144:0] fp_cpx; |
|
os2wb os2wb_inst ( |
.clk(sys_clock_i), |
.rstn(~sys_reset_final), |
|
.pcx_req(spc_pcx_req_pq), |
.pcx_atom(spc_pcx_atom_pq), |
.pcx_data(spc_pcx_data_pa), |
.pcx_grant(pcx_spc_grant_px), |
.cpx_ready(cpx_spc_data_rdy_cx2), |
.cpx_packet(cpx_spc_data_cx2), |
.wb_data_i(wbm_data_i), |
.wb_ack(wbm_ack_i), |
.wb_cycle(wbm_cycle_o), |
.wb_strobe(wbm_strobe_o), |
.wb_we(wbm_we_o), |
.wb_sel(wbm_sel_o), |
.wb_addr(wbm_addr_o), |
.wb_data_o(wbm_data_o), |
|
.fp_pcx(fp_pcx), |
.fp_req(fp_req), |
.fp_cpx(fp_cpx), |
.fp_rdy(fp_rdy!=8'h00), |
|
.eth_int(0/*eth_irq_i*/) |
); |
|
// FPU |
fpu fpu_inst( |
.pcx_fpio_data_rdy_px2(fp_req), |
.pcx_fpio_data_px2(fp_pcx), |
.arst_l(cmp_arst_l), |
.grst_l(cmp_grst_l), |
.gclk(gclk), |
.cluster_cken(cluster_cken), |
|
.fp_cpx_req_cq(fp_rdy), |
.fp_cpx_data_ca(fp_cpx), |
|
.ctu_tst_pre_grst_l(ctu_tst_pre_grst_l), |
.global_shift_enable(global_shift_enable), |
.ctu_tst_scan_disable(ctu_tst_scan_disable), |
.ctu_tst_scanmode(ctu_tst_scanmode), |
.ctu_tst_macrotest(ctu_tst_macrotest), |
.ctu_tst_short_chain(ctu_tst_short_chain), |
|
.si(0), |
.so() |
); |
|
wire fp_req; |
wire [123:0] fp_pcx; |
wire [ 7:0] fp_rdy; |
wire [144:0] fp_cpx; |
|
os2wb_dual os2wb_inst ( |
.clk(sys_clock_i), |
.rstn(~sys_reset_final), |
|
.pcx_req(spc_pcx_req_pq), |
.pcx_atom(spc_pcx_atom_pq), |
.pcx_data(spc_pcx_data_pa), |
.pcx_grant(pcx_spc_grant_px), |
.cpx_ready(cpx_spc_data_rdy_cx2), |
.cpx_packet(cpx_spc_data_cx2), |
|
.pcx1_req(spc1_pcx_req_pq), |
.pcx1_atom(spc1_pcx_atom_pq), |
.pcx1_data(spc1_pcx_data_pa), |
.pcx1_grant(pcx1_spc_grant_px), |
.cpx1_ready(cpx1_spc_data_rdy_cx2), |
.cpx1_packet(cpx1_spc_data_cx2), |
|
.wb_data_i(wbm_data_i), |
.wb_ack(wbm_ack_i), |
.wb_cycle(wbm_cycle_o), |
.wb_strobe(wbm_strobe_o), |
.wb_we(wbm_we_o), |
.wb_sel(wbm_sel_o), |
.wb_addr(wbm_addr_o), |
.wb_data_o(wbm_data_o), |
|
.fp_pcx(fp_pcx), |
.fp_req(fp_req), |
.fp_cpx(fp_cpx), |
.fp_rdy(fp_rdy!=8'h00), |
|
.eth_int(0/*eth_irq_i*/) |
); |
|
// FPU |
fpu fpu_inst( |
.pcx_fpio_data_rdy_px2(fp_req), |
.pcx_fpio_data_px2(fp_pcx), |
.arst_l(cmp_arst_l), |
.grst_l(cmp_grst_l), |
.gclk(gclk), |
.cluster_cken(cluster_cken), |
|
.fp_cpx_req_cq(fp_rdy), |
.fp_cpx_data_ca(fp_cpx), |
|
.ctu_tst_pre_grst_l(ctu_tst_pre_grst_l), |
.global_shift_enable(global_shift_enable), |
.ctu_tst_scan_disable(ctu_tst_scan_disable), |
.ctu_tst_scanmode(ctu_tst_scanmode), |
.ctu_tst_macrotest(ctu_tst_macrotest), |
.ctu_tst_short_chain(ctu_tst_short_chain), |
|
.si(0), |
.so() |
); |
|
/* |
* Reset Controller |
*/ |
259,6 → 324,7
*/ |
|
assign const_cpuid = 4'h0; |
assign const_cpuid1 = 4'h1; |
assign const_maskid = 8'h20; |
|
// sscan |
/PROM/2c1t_obp_prom.rar
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
PROM/2c1t_obp_prom.rar
Property changes :
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: PROM/2c4t_obp_prom.rar
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: PROM/2c4t_obp_prom.rar
===================================================================
--- PROM/2c4t_obp_prom.rar (nonexistent)
+++ PROM/2c4t_obp_prom.rar (revision 6)
PROM/2c4t_obp_prom.rar
Property changes :
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property