Line 28... |
Line 28... |
input [123:0] pcx_data,
|
input [123:0] pcx_data,
|
output reg [ 4:0] pcx_grant,
|
output reg [ 4:0] pcx_grant,
|
output reg cpx_ready,
|
output reg cpx_ready,
|
output reg [144:0] cpx_packet,
|
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
|
// Wishbone master interface
|
input [ 63:0] wb_data_i,
|
input [ 63:0] wb_data_i,
|
input wb_ack,
|
input wb_ack,
|
output reg wb_cycle,
|
output reg wb_cycle,
|
output reg wb_strobe,
|
output reg wb_strobe,
|
Line 123... |
Line 131... |
reg [ 4:0] pcx_req_2;
|
reg [ 4:0] pcx_req_2;
|
reg pcx_atom_1;
|
reg pcx_atom_1;
|
reg pcx_atom_2;
|
reg pcx_atom_2;
|
reg pcx_data_123_d;
|
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)
|
always @(posedge clk)
|
begin
|
begin
|
pcx_req_1<=pcx_req;
|
pcx_req_1<=pcx_req;
|
pcx_atom_1<=pcx_atom;
|
pcx_atom_1<=pcx_atom;
|
pcx_atom_2<=pcx_atom_1;
|
pcx_atom_2<=pcx_atom_1;
|
pcx_req_2<=pcx_atom_1 ? pcx_req_1:5'b0;
|
pcx_req_2<=pcx_atom_1 ? pcx_req_1:5'b0;
|
pcx_grant<=(pcx_req_1 | pcx_req_2);
|
pcx_grant<=(pcx_req_1 | pcx_req_2);
|
pcx_data_123_d<=pcx_data[123];
|
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
|
end
|
|
|
pcx_fifo pcx_fifo_inst(
|
pcx_fifo pcx_fifo_inst(
|
// FIFO should be first word fall-through
|
// FIFO should be first word fall-through
|
// It has no full flag as the core will send only limited number of requests,
|
// It has no full flag as the core will send only limited number of requests,
|
Line 150... |
Line 174... |
// Second atomic packet for FPU may be invalid, but should be sent to FPU
|
// 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
|
// so if the first atomic packet is valid we latch both
|
.empty(pcx_fifo_empty),
|
.empty(pcx_fifo_empty),
|
.q(pcx_data_fifo)
|
.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;
|
reg wb_ack_d;
|
|
|
always @(posedge clk or negedge rstn)
|
always @(posedge clk or negedge rstn)
|
Line 169... |
Line 211... |
if(eth_int_sent)
|
if(eth_int_sent)
|
eth_int_send<=0;
|
eth_int_send<=0;
|
end
|
end
|
|
|
reg fifo_rd;
|
reg fifo_rd;
|
|
reg fifo_rd1;
|
wire [123:0] pcx_packet;
|
wire [123:0] pcx_packet;
|
assign pcx_packet=pcx_data_fifo[123:0];
|
assign pcx_packet=cpu ? pcx1_data_fifo[123:0]:pcx_data_fifo[123:0];
|
|
reg cpu;
|
|
reg cpu2;
|
|
|
always @(posedge clk or negedge rstn)
|
always @(posedge clk or negedge rstn)
|
if(rstn==0)
|
if(rstn==0)
|
begin
|
begin
|
if(`TEST_DRAM)
|
if(`TEST_DRAM)
|
Line 291... |
Line 336... |
`PCX_IDLE:
|
`PCX_IDLE:
|
begin
|
begin
|
cnt<=0;
|
cnt<=0;
|
cpx_packet<=145'b0;
|
cpx_packet<=145'b0;
|
cpx_ready<=0;
|
cpx_ready<=0;
|
|
cpx1_packet<=145'b0;
|
|
cpx1_ready<=0;
|
cpx_two_packet<=0;
|
cpx_two_packet<=0;
|
multi_hit<=0;
|
multi_hit<=0;
|
multi_hit1<=0;
|
multi_hit1<=0;
|
if(eth_int_send)
|
if(eth_int_send)
|
begin
|
begin
|
Line 306... |
Line 353... |
begin
|
begin
|
pcx_req_d<=pcx_data_fifo[128:124];
|
pcx_req_d<=pcx_data_fifo[128:124];
|
pcx_atom_d<=pcx_data_fifo[129];
|
pcx_atom_d<=pcx_data_fifo[129];
|
fifo_rd<=1;
|
fifo_rd<=1;
|
state<=`GOT_PCX_REQ;
|
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
|
end
|
end
|
`GOT_PCX_REQ:
|
`GOT_PCX_REQ:
|
begin
|
begin
|
pcx_packet_d<=pcx_packet;
|
pcx_packet_d<=pcx_packet;
|
Line 320... |
Line 379... |
end
|
end
|
if(pcx_packet[103:64]==40'h9800000800 && pcx_packet[122:118]==5'b00001)
|
if(pcx_packet[103:64]==40'h9800000800 && pcx_packet[122:118]==5'b00001)
|
begin
|
begin
|
state<=`CPX_INT_VEC_DIS;
|
state<=`CPX_INT_VEC_DIS;
|
fifo_rd<=0;
|
fifo_rd<=0;
|
|
fifo_rd1<=0;
|
end
|
end
|
else
|
else
|
if(pcx_atom_d==0)
|
if(pcx_atom_d==0)
|
begin
|
begin
|
fifo_rd<=0;
|
fifo_rd<=0;
|
|
fifo_rd1<=0;
|
if(pcx_packet[122:118]==5'b01010) // FP req
|
if(pcx_packet[122:118]==5'b01010) // FP req
|
begin
|
begin
|
state<=`PCX_FP_1;
|
state<=`PCX_FP_1;
|
pcx_packet_2nd[123]<=0;
|
pcx_packet_2nd[123]<=0;
|
end
|
end
|
Line 343... |
Line 404... |
pcx_packet_2nd<=pcx_packet; //Latch second packet for atomics
|
pcx_packet_2nd<=pcx_packet; //Latch second packet for atomics
|
if(`DEBUGGING)
|
if(`DEBUGGING)
|
if(pcx_fifo_empty)
|
if(pcx_fifo_empty)
|
wb_sel<=8'h67;
|
wb_sel<=8'h67;
|
fifo_rd<=0;
|
fifo_rd<=0;
|
|
fifo_rd1<=0;
|
if(pcx_packet_d[122:118]==5'b01010) // FP req
|
if(pcx_packet_d[122:118]==5'b01010) // FP req
|
state<=`PCX_FP_1;
|
state<=`PCX_FP_1;
|
else
|
else
|
state<=`PCX_REQ_STEP1;
|
state<=`PCX_REQ_STEP1;
|
end
|
end
|
Line 362... |
Line 424... |
cpx_packet_1[135:134]<=pcx_packet_d[113:112]; // Thread ID
|
cpx_packet_1[135:134]<=pcx_packet_d[113:112]; // Thread ID
|
cpx_packet_1[133:131]<=0; // Way valid
|
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[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[129]<=pcx_atom_d;
|
cpx_packet_1[128]<=pcx_packet_d[110]; // Prefetch
|
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};
|
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;
|
state<=`CPX_READY_1;
|
end
|
end
|
else
|
else
|
if(pcx_packet_d[122:118]!=5'b01001) // Not INT
|
if(pcx_packet_d[122:118]!=5'b01001) // Not INT
|
begin
|
begin
|
Line 384... |
Line 446... |
wb_addr<={pcx_req_d,19'b0,pcx_packet_d[103:64+3],3'b000};
|
wb_addr<={pcx_req_d,19'b0,pcx_packet_d[103:64+3],3'b000};
|
wb_data_o<=pcx_packet_d[63:0];
|
wb_data_o<=pcx_packet_d[63:0];
|
state<=`PCX_REQ_STEP1_1;
|
state<=`PCX_REQ_STEP1_1;
|
end
|
end
|
else
|
else
|
if((pcx_packet_d[12:10]!=3'b000) && !pcx_packet_d[117]) // Not FLUSH int and not this core
|
//if((pcx_packet_d[12:10]!=3'b000) && !pcx_packet_d[117]) // Not FLUSH int and not this core
|
state<=`PCX_IDLE;
|
// state<=`PCX_IDLE;
|
else
|
//else
|
state<=`CPX_READY_1;
|
state<=`CPX_READY_1;
|
case(pcx_packet_d[122:118]) // Packet type
|
case(pcx_packet_d[122:118]) // Packet type
|
5'b00000://Load
|
5'b00000://Load
|
begin
|
begin
|
wb_we<=0;
|
wb_we<=0;
|
Line 511... |
Line 573... |
wb_we<=0; // Load first, as CAS
|
wb_we<=0; // Load first, as CAS
|
wb_sel<=8'b11111111; // SWAP/LDSTUB loads are as cacheline
|
wb_sel<=8'b11111111; // SWAP/LDSTUB loads are as cacheline
|
end
|
end
|
5'b01001://INT
|
5'b01001://INT
|
if(pcx_packet_d[117]) // Flush
|
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
|
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
|
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]};
|
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'b01010: FP1 - processed by separate state
|
//5'b01011: FP2 - processed by separate state
|
//5'b01011: FP2 - processed by separate state
|
//5'b01101: FWDREQ - not implemented
|
//5'b01101: FWDREQ - not implemented
|
//5'b01110: FWDREPL - not implemented
|
//5'b01110: FWDREPL - not implemented
|
5'b10000://IFILL
|
5'b10000://IFILL
|
Line 652... |
Line 722... |
endcase
|
endcase
|
end
|
end
|
5'b00001://Store
|
5'b00001://Store
|
begin
|
begin
|
cpx_packet_1[143:140]<=4'b0100; // Type
|
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};
|
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
|
// 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;
|
// state<=`PCX_BIS;
|
// else
|
// else
|
// begin
|
// begin
|
wb_cycle<=0;
|
wb_cycle<=0;
|
Line 665... |
Line 735... |
end
|
end
|
5'b00010://CAS
|
5'b00010://CAS
|
begin
|
begin
|
cpx_packet_1[143:140]<=4'b0000; // Load return for first packet
|
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[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_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};
|
cpx_packet_1[127:0]<={wb_data_i,wb_data_i};
|
state<=`PCX_REQ_STEP2;
|
state<=`PCX_REQ_STEP2;
|
end
|
end
|
5'b00100://STRLOAD
|
5'b00100://STRLOAD
|
begin
|
begin
|
Line 929... |
Line 999... |
eth_int_sent<=0;
|
eth_int_sent<=0;
|
state<=`CPX_READY_1;
|
state<=`CPX_READY_1;
|
end
|
end
|
`CPX_INT_VEC_DIS:
|
`CPX_INT_VEC_DIS:
|
begin
|
begin
|
if(pcx_packet_d[12:10]==3'b000)
|
//if(pcx_packet_d[12:10]==3'b000) // Send interrupt only if it is for this core
|
cpx_two_packet<=1; // 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[144:140]<=5'b10100;
|
cpx_packet_1[139:137]<=0;
|
cpx_packet_1[139:137]<=0;
|
cpx_packet_1[136]<=1;
|
cpx_packet_1[136]<=1;
|
cpx_packet_1[135:134]<=pcx_packet_d[113:112]; // Thread ID
|
cpx_packet_1[135:134]<=pcx_packet_d[113:112]; // Thread ID
|
cpx_packet_1[133:130]<=0;
|
cpx_packet_1[133:130]<=0;
|
cpx_packet_1[129]<=pcx_atom_d;
|
cpx_packet_1[129]<=pcx_atom_d;
|
cpx_packet_1[128]<=0;
|
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_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]};
|
cpx_packet_2<={9'h170,54'h0,pcx_packet_d[17:0],46'h0,pcx_packet_d[17:0]};
|
state<=`CPX_READY_1;
|
state<=`CPX_READY_1;
|
end
|
end
|
`CPX_READY_1:
|
`CPX_READY_1:
|
begin
|
begin
|
|
if(!cpu)
|
|
begin
|
cpx_ready<=1;
|
cpx_ready<=1;
|
cpx_packet<=cpx_packet_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;
|
cnt<=cnt+1;
|
if(`DEBUGGING)
|
if(`DEBUGGING)
|
if(multi_hit || multi_hit1)
|
if(multi_hit || multi_hit1)
|
wb_sel<=8'h11;
|
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;
|
state<=`CPX_READY_2;
|
end
|
end
|
`CPX_READY_2:
|
`CPX_READY_2:
|
begin
|
begin
|
|
if(cpx_two_packet && !cpu2)
|
|
begin
|
cpx_ready<=1;
|
cpx_ready<=1;
|
cpx_packet<=cpx_packet_2;
|
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;
|
state<=`PCX_IDLE;
|
end
|
end
|
`PCX_UNKNOWN:
|
`PCX_UNKNOWN:
|
begin
|
begin
|
wb_sel<=8'b10100101; // Illegal eye-catching value for debugging
|
wb_sel<=8'b10100101; // Illegal eye-catching value for debugging
|
Line 973... |
Line 1088... |
|
|
l1dir l1dir_inst(
|
l1dir l1dir_inst(
|
.clk(clk),
|
.clk(clk),
|
.reset(!rstn),
|
.reset(!rstn),
|
|
|
.cpu(0), // Issuing CPU number
|
.cpu(cpu), // Issuing CPU number
|
.strobe(state==`GOT_PCX_REQ),
|
.strobe(state==`GOT_PCX_REQ),
|
.way(pcx_packet[108:107]), // Way to allocate for allocating loads
|
.way(pcx_packet[108:107]), // Way to allocate for allocating loads
|
.address(pcx_packet[64+39:64]),
|
.address(pcx_packet[64+39:64]),
|
.load(pcx_packet[122:118]==5'b00000),
|
.load(pcx_packet[122:118]==5'b00000),
|
.ifill(pcx_packet[122:118]==5'b10000),
|
.ifill(pcx_packet[122:118]==5'b10000),
|