VHDL Files

advertisement
Issue Bus Fields
Shift Function
OP function
0
sll
1
N/A
2
sra
3
srl
ALU
OP
Same as ALU unit
Issue Bus
Type ROB
Set
Numbits
4
1
Issue Bus
Type ROB
Op
Numbits
4
2
VkValid
1
Vk
32
Shamt
5
Qk
4
Total Bits: 48
Vj
32
VkValid
1
Vk
32
Qj
4
Qk
4
Total Bits: 48
Vj
32
VkValid
1
Vk
32
Qj
4
Qk
4
Total Bits: 79
Type predict Vjvalid Vkvalid
Numbits
1
1
1
OP
2
ROB
4
Type
Numbits
Qk
4
PC
32
Qj
4
Vj
32
SetU ALUop VjValid
1
3
1
Mult
OP function Type ROB
0
mult Numbits
4
1
div
Branch
OP function
0
beq
1
bne
2
bgez
3
bltz
OP
1
Vj
32
VjValid
1
Vk
32
Qj
4
Move
OP function
0
lo
1
hi
Type ROB
Numbits
4
OP
1 Total Bits: 5
MemOP
OP function
0
lw
1
sw
Type ROB
Numbits
4
OP
1
Vjvalid
1
otherPC
32
Total Bits: 144
iMem
32
Jr
Type ROB VjValid
Numbits
4
1
Jal
Type ROB
Numbits
4
PC+8
32
Qj
4
Vj
32Total Bits: 37
Total Bits: 74
Appendix I – Notebooks:
Phoebus Chen
= Index =========================================================
Mon Apr 23 16:00:29 PDT 2001 - Group discussion on how to split up work.
Wed Apr 25 16:58:12 PDT 2001 - Planning for Branch prediction.
Fri Apr 27 01:41:51 PDT 2001 - drew 2 bit predictor and starting branch
predictor.
Fri Apr 27 18:45:02 PDT 2001 - Finished making symbol for branch history table.
Mon Apr 30 01:01:29 PDT 2001 - Finished making branch history table entry.
Mon Apr 30 17:52:13 PDT 2001 - Finished making branch prediction unit, changed
branch history table entry, untested.
Fri May
4 23:49:00 PDT 2001 - Finished writing VHDL for testing branch
predictor, but doesn't compile.
Sat May
5 17:20:15 PDT 2001 - Got testbench for branch predictor to compile
but branch predictor fails.
Sun May 6 23:37:26 PDT 2001 - Debugged more of branch predictor.
(- 2 hours for dinner break)
Mon May
7 17:38:19 PDT 2001 - Got tester working.
Tue May
8 00:07:35 PDT 2001 - Finished testing branch predictor, fixed some
bugs (we didn't test branch addresses before).
Wed May 9 01:38:55 PDT 2001 - Almost completed building branch validation unit.
(- 2 hours for dinner break)
Time Spent:
=================================================================
+++ Mon Apr 23 12:15:41 PDT 2001 ================================
Goal: Figure out how to do branch prediction.
We divided up the work for Tomasulo today.
I got to do branch prediction.
For branch prediction, I need to build a cache of past branches
branch predictor. I also need to pass the address of the branch that
the branch FU reservation station. I'll be working with Manda on how
instruction quickly, and squashing. It's likely that I'll be working
as well.
and the 2 bit
I didn't take to
to issue the next
on the branch unit
--- Mon Apr 23 16:00:29 PDT 2001 ================================
+++ Wed Apr 25 14:32:23 PDT 2001 ================================
Goal: Layout branch prediction unit's I/O.
* We always don't branch the first time we see a new branch instruction.
* remember to give an invalid_next signal to Manda, so that when we invalidate a branch,
she will throw away the next instruction fetched from memory.
* if a previous branch was incorrect, we flush all instructions after it. This means
that if we get a "branch_invalid" signal, the nextPC mux will not see the result of the
branch predictor unit. This means the branch prediction unit needs not update the
history table until the transition at the beginning of the next cycle.
Branch History Table:
Entries:
PC
valid bit
PC + Immediate (branch)
2 bits for taken/not taken
Tag comparator
2 bit state machine
ALU - for new branches, to calculate branch to address and store in table
Branch Validation FU:
Comparator
register storing non-predicted address
reservation station
*ALG* Branch Prediction (direct mapped, simple 2-bit):
At clock edge, latch in updated entry if misprediction in previous cycle.
||Check Opcode for branch
||Calculate branch address (immed + PC, in ALU)
||Use lower part of PC to index table
||check valid bit
||check tag with PC
||check taken/not taken
||fetch branch address
if (branch_opcode) then
if (not_valid or not_tag_match) then
nextPC_mux_sel chooses PC+4 //predict not branch
store new calculated branch address to table (next cycle)
elseif (taken) then
nextPC_mux_sel chooses branch address from table
else //not taken
nextPC_mux_sel chooses PC+4
endif
endif
Haven't coded anything yet today.
--- Wed Apr 25 16:58:12 PDT 2001 ================================
+++ Fri Apr 27 00:39:23 PDT 2001 ================================
Goal: Build 2 bit predictor and test unit.
Too tired.
predictor.
I built the untested 2 bit predictor and drew an alu for the branch
I kmapped the 2 bit predictor.
--- Fri Apr 27 01:41:51 PDT 2001 ================================
+++ Fri Apr 27 16:47:09 PDT 2001 ================================
Goal: Finish Branch History Table.
Finished the symbol for the Branch History Table, but not the schematic yet.
--- Fri Apr 27 18:45:02 PDT 2001 ================================
+++ Sun Apr 29 22:39:03 PDT 2001 ================================
Goal: Finish Branch predictor.
Ack, still didn't finish building it. Once I finish building the branch history table, I
should be able to begin testing. I did finish the branch history table entry, however.
--- Mon Apr 30 01:01:29 PDT 2001 ================================
+++ Mon Apr 30 14:48:08 PDT 2001 ================================
Goal: Finish Branch Predictor and Start planning for branch unit.
Okay, after talking with JimmyD I realized how stupid it is to store the target branch
address considering that it's not a bottleneck for the branch prediction unit - it can
still complete in one cycle with an adder. I'll continue to store the tag so that we
don't branch predict for different instructions, I suppose. This may make debugging
easier.
Yes, finished the branch predictor. It's really simple now.
building the validation unit. Shouldn't be too bad.
Next comes testing and
--- Mon Apr 30 17:52:13 PDT 2001 ================================
+++ Fri May
4 22:20:11 PDT 2001 ================================
Goal: Test Branch Predictor, look at branch validation unit.
Well, I finished compiling all the files and i write the VHDL file, but I'm having
problems compiling it. Will look at this tomorrow.
--- Fri May
4 23:49:00 PDT 2001 ================================
+++ Sat May
5 14:08:05 PDT 2001 ================================
Goal: Finish Testing Branch Predictor and build branch validation unit.
Ack, I got the testbench to compile, but my component is failing the tests. Will keep
testing tomorrow (I hate VHDL, wasted so many hours getting the testbench to compile and
run correctly).
--- Sat May
5 17:20:15 PDT 2001 ================================
+++ Sun May
6 09:13:44 PDT 2001 ================================
Goal: Get Branch Predictor Working.
I realized that I made some really stupid mistakes yesterday, like not having CLK and
RESET pins into my branch predictor.
I also realized that i should not use the lower 2 bits of the PC as the index into the
branch table (they're always 00).
I didn't get to finish changing the pins on the decoder in bhtable (I just realized there
were bars over all of the outputs!)
Gotta go.
--- Sun May
6 10:58:57 PDT 2001 ================================
+++ Sun May
6 16:57:12 PDT 2001 ================================
Goal: GET BRANCH PREDICTION WORKING!!!!!
Okay, I've taken a 2 hour dinner break, so that doesn't count to my time total.
I've found various bugs in my branch predictor... didn't bother documenting them
because this is still initial testing.
tags.
I made a fundamental design change... I'm no longer keeping track of the branch
Now, my branch history table entries look wimpy.
I don't know what's wrong with the testbench tests, but the original ones work
fine.
Another frustrating day....IT'S STILL NOT WORKING WITH TESTBENCHES.
--- Sun May 6 23:37:26 PDT 2001 ================================
+++ Mon May
7 12:36:53 PDT 2001 ================================
Goal: debug testbench?
Make branch validation unit.
I'll need 1 FF to store branch prediction result and 32 bit register to store not taken
value.
Yea! I finally got the testbench to work. I made a schematic and a symbol for the
testbench, changed a few things for the testbench, then tested through this.
All tests have passed thus far.
Dinner break!
--- Mon May 7 17:38:19 PDT 2001 ================================
+++ Mon May
7 18:28:52 PDT 2001 ================================
Goal: write more test cases for testbench.
Yes, it passes most of my test cases. Checks that:
1) the 2 bit predictor works - to saturation, toggling TFTF
2) updates can happen while another entry is being accessed
3) instructions that should collide in the branch history table actually affect the same
entry
4) non-branch instructions don't cause branches
5) both bne and beq are recognized
I have used 20 ns delays, because the components are not optimized (I'm using ALU, mux,
and tristate in critical path).
I also added in testing for the untaken address and the new branch address, to make sure
they were computed properly.
--- Tue May 8 00:07:35 PDT 2001 ================================
+++ Tue May
8 11:05:08 PDT 2001 ================================
Goal: Finish building branch validation unit.
Okay, I didn't build the unit yet. I was looking at Mark's schematic to see how it
works. There are some questions I have of his implementation.
--- Tue May
8 12:09:07 PDT 2001 ================================
+++ Tue May
8 15:54:04 PDT 2001 ================================
Goal: Finish building branch validation unit.
The main changes from Mark's ALU reservation station is that I've added the
UNTAKEN_ADDR[31:0] and B_TAKEN value to be stored in the stations and I've changed the
ISSUE[112:0] bus values that feed into each register in the reservation station.
I've also removed unnecessary pins from each reservation station and made the symbol
bigger.
Here's the values from the branch issue bus, as given to me by Po:
Name
numbits
range
predict
1
[144]
Vjvalid
1
[143]
Vkvalid
1
[142]
OP
2
[141:140]
ROB
4
[139:136]
Vj
32
[135:104]
Vk
32
[103:72]
Qj
4
[71:68]
Qk
4
[67:64]
PC
32
[63:32]
otherPC
32
[31:0]
Here's
beq =
bne =
bgez =
bltz =
the opcodes, from Po:
00
01
10
11
1 hour dinner break.
Almost done with branch validation unit, just have to fix the control.
squishers!
--- Wed May
9 01:38:55 PDT 2001 ================================
+++ Wed May
9 13:49:24 PDT 2001 ================================
Even has
Goal: Finish building branch validation unit.
Koichi has taken on the jump register unit.
I used Mark's RSctrlShift units, and edited it to remove the issue[84:0] pin because it's
not used.
Here's the values from the jal issue bus:
Name
numbits
range
ROB
4
[35:32]
PC
32
[31:0]
(- 40 minutes for HKN meeting)
(- 2 hours for HKN meeting)
Just got the jal unit finished... pretty easy.
Now I'm working on the mfhi, mflo units...
Here's the values from the move issue bus:
Name
numbits
range
OP
1
[73]
valuevalid 1
[72]
waitMulROB 4
[71:68]
ROB
4
[67:64]
HILO
64
[63:0]
These are not in the issue bus:
mult_not_done
MulROB
4
HI
32
[63:32]
LO
32
[31:0]
Mark Chew
Mon Apr 23 17:43:41 PDT 2001 - Just brainstorming about what it's going to take.
Tue Apr 24 16:27:57 PDT 2001 - Got reservation station schematics drawn.
Wed Apr 25 16:00:48 PDT 2001 - Got framework of RS controller.
Thu Apr 26 21:49:16 PDT 2001 - Started multiply unit
Sat Apr 28 15:01:12 PDT 2001 - Working on VHDL for RS controllers
Wed May 2 23:48:03 PDT 2001 - Wrote most of the code for ALU RS controller.
to debug.
Still have
Fri May 4 00:23:32 PDT 2001 - Finished preliminary version of ALU RS controller. Also
wrote the initial test file for it; just need to resolve technical difficulties next
time.
Fri May 4 18:36:59 PDT 2001 - More stuff with the arithmetic units.
right, but the RS controller still needs some major work.
Got a slt working
Sat May 5 22:38:53 PDT 2001 - Got some instructions executing, but I still need to work
on timing.
Tue May 8 00:10:08 PDT 2001 - Got ALU-related instructions working.
the CDB, and drive the CDB properly now, I think.
They stall, request
Wed May 9 01:02:19 PDT 2001 - Got Shift-related instructions working and improved the
algorithm that decides which RS to launch. Now need to work on the multiplying next.
Thu May 10 07:18:49 PDT 2001 - I hate CS 152.
===============================================================================
Mon Apr 23 14:32:34 PDT 2001
Discussed project as a group.
Argh!!!
I doesn't work.
Going to get asynchronous DRAM controller working now.
We're going to have to ask James or something about this one.
Forget it. Going to work on the reservation stations.
An RS needs: name, busy(not available), Op, Vj, Vk, Qj, Qk
It also needs some abstractions, like "source operand ready" or ...
When source operands are ready, it's going to be really hard to nullify Qj and write Vj
in hardware, all at the same time.
Also, RS's need to have some way of interfacing with the CDB. Argh...this is really
really complicated.
Mon Apr 23 17:43:41 PDT 2001 (3 hours)
------------------------------------------------------------------------------Tue Apr 24 15:40:33 PDT 2001
Goal: Get reservation stations moving!!
I'm not quite sure when a reservation station would be busy, but not have an OP, or have
an OP, but not be busy.
Not sure how to identify each RS. For now, I'm just going to have people wire it up from
the outside. So it just returns whatever name you give it.
Reservation stations done, in gates. I don't think there's a need to test yet, since
everything is pretty self-explanatory and basic. The next task I need to do is build the
RS controller. This would be difficult because I'm not going to know exactly the format
of the instruction issues. Also, it's going to need to arbitrate and choose which RS
under its domain gets to use the functional unit, if 2 RS's become ready at the same
time.
Tue Apr 24 16:27:57 PDT 2001 (1 hour)
------------------------------------------------------------------------------Wed Apr 25 14:07:48 PDT 2001
Goal: Do about half of RS controller
Got framework of RS controller.
Dang.
This thing's complicated.
Wed Apr 25 16:00:48 PDT 2001 (2 hours)
------------------------------------------------------------------------------Thu Apr 26 15:18:30 PDT 2001
Goal: Understand the interfaces that the RS controller is going to do, and start working
on some vhdl for it.
We need sets of RS's for shifts, ALU-related operations, multiplies and branches.
project is seeming as difficult as ever.
Working on multiply
Thu Apr 26 21:49:16 PDT 2001 (5.5 hours)
------------------------------------------------------------------------------Sat Apr 28 13:07:20 PDT 2001
Goal: Get working on RS controller, in VHDL.
It's coming...slowly.
Sat Apr 28 15:01:12 PDT 2001 (2 hours)
------------------------------------------------------------------------------Wed May 2 14:22:19 PDT 2001
This
I think the reservation stations should be more intelligent than they are now. Right
now, they're just a collection of flip-flops, but I think they should be able to listen
to the CDB and know when to latch stuff in, instead of relying on the RS controllers.
Ok, now a reservation station only needs to know when it can latch stuff. It can sit on
the bus and just automatically know whether to listen to a valud. Still, it needs to be
able to launch instructions correctly.
Wed May
2 16:06:25 PDT 2001
Wed May
Back
2 18:47:30 PDT 2001 (minus 2.5 hours)
I *think* the reservation station module is done. The RS controller just needs to raise
"go" on the cycle that the execution of that instruction gets put into a functional unit,
and raise "reset" for a cycle at the completion of the functional unit's execution. This
changes the RS controllers big-time, but this is a good change, since it's a change for
the better (simpler).
I need to ask Po what happens on a set.
How do I tell what kind of set it is?
Aha! If I want to use the CDB on a specific cycle, I'm going to have to request it the
cycle before that. For ALU operations, that means that I need to request during the
cycle that I launch.
Ok, code for the ALU RS controller is getting filled in now.
matter of debugging this stuff.
Soon, it'll just be a
Wed May 2 23:48:03 PDT 2001 (7 hours)
------------------------------------------------------------------------------Thu May 3 15:40:56 PDT 2001
Goal: Have RS controllers done to my satisfaction, and start working on multiplier and
divider units.
Aha!!! There is a SEPARATE EX and WB stage. This means that as long as I request the
CDB during the EX stage, then most of the time the WB stage can go smoothly. Also, If I
latch the output of the EX stage, I can pipeline everything so that the FU stays busy all
the time.
A complexity problem with this is that the RS controller has to stall everything when it
doesn't get the CDB. This means not letting the flip-flop get written and putting the
same values into the ALU.
Remind Po that we've changed the interface, adding more information so that signed and
unsigned sets will work in the ALU unit.
Changing the issue "standard" to make debugging a lot easier.
Ok, the initial test file is written. I still need to figure out the compile/fusion
errors, but I think this is a good stopping point.
(minus 1.5 hours for dinner and watching Diehard)
Fri May 4 00:23:32 PDT 2001 (8 hours)
------------------------------------------------------------------------------Fri May 4 14:43:28 PDT 2001
Ok, got one instruction that came out correctly. Dang, it took forever for me to get the
logic at the end right. But I still need to worry about the RS controller, which is my
main task. It still doesn't seem to be conducting things the right way.
Fri May 4 18:36:59 PDT 2001 (4 hours)
------------------------------------------------------------------------------Sat May 5 10:56:19 PDT 2001
Goal: Get all the ALU-related instructions working.
Minus 2.5 hours for acupuncture.
Right now, the issue unit seems to be working OK, but the launch doesn't.
Now, the instructions are executing and coming out at Dout correctly. However I'm still
having a few timing problems. One thing is, it seems like I usually have trouble
executing instructions every cycle. I'm seeing a bunch of zeros between every meaningful
set of values going into the ALU. Also, I'm having trouble with the CDBrequest. I need
an asynchronous arbiter so that I can get the CDB the cycle AFTER I launch. However, I'm
having problems with this. The request needs to happen each time I launch an instruction
AND each time I have an instruction that still needs to broadcast. How to do this is not
clear to me, but I'm so brain-dead from this whole day of working that I need to stop
now.
Sat May 5 22:38:53 PDT 2001 (9 hours)
------------------------------------------------------------------------------Mon May 7 12:21:25 PDT 2001
Goal: Get ALU-related instructions totally working.
After 11.5 hours, it's finally working.
units.
Now going to port everything over to the shift
We need to improve the launch algorithm so that it picks the oldest instruction to
launch. Koichi will work on this. Tomorrow, I need to do the shifter and the
multiply/divide units.
Minus 4 hours for discussion and break
Tue May 8 00:10:08 PDT 2001 - (8 hours)
------------------------------------------------------------------------------Tue May 8 15:57:29 PDT 2001
Working on algorithm and the shifts.
Koichi did a good job on the algorithm so making the shifts work wasn't too much work.
Yay!
Minus a lot of time for breaks.
Wed May 9 01:02:19 PDT 2001 (~ 4 hours) 53.5 hours so far
------------------------------------------------------------------------------Wed May 9 15:50:35 PDT 2001
Goal: Get multiplier and divider working.
Darn it.
Giving up on mult and div.
Insight: if we eventually decide to support branch prediction, I'm going to have to
modify the launch unit. It needs to not launch when the squish signal is high.
Darn it. Why am I still here?
Thu May 10 07:18:49 PDT 2001 (15.5 hours) 69 hours so far
-------------------------------------------------------------------------------
Manda Sutijono
----------------------------------------------------------------------------------------*Start: Mon Apr 23 14:12:50 PDT 2001
Met with group to talk about final project. We split up Tomasulu into parts. I'll be
working on the op queue. Looks like we're making it circular, and having 2 counters, the
head and tail. The size will be probably twice that of the reorder buffer. So first
I'll make it 16, since Koichi's going to first make the reorder buffer 8. I'll also need
to make sure to reset the counter and place it correctly for when squashing occurs.
So far I've just placed 16 32-bit registers into the op_queue schematic.
more on Tomasulu tomorrow.
Going to read
*End: Mon Apr 23 16:21:34 PDT 2001
Approx. total: 2 hours
-----------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------*Start: Wed Apr 25 14:16:27 PDT 2001
Working on the op queue. I also have to add when to issue instructions. I must check if
there's an empty reservation station and an empty slot in the reorder buffer. If all
reservations are full or reorder buffer is full, the instruction issue is stalled until
both have available entries.
We just talked and now we decided that Po will handle the issuing. Also, I'll have to
look and see whether an instruction is j, jal, or jr. For a jr instruction, the delay
slot will be freezed until a signal comes from Po. Also, Phoebus needs another input to
the PC mux for branch prediction.
*End: Wed Apr 25 16:00:12 PDT 2001
Approx. total: 2 hours
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*Start: Fri Apr 27 20:36:04 PDT 2001
Finally done with 164, so now I can concentrate on this op queue.
Haven't done much. Just put in the register enable signals that come from the head
counter. I have to finish labelling tomorrow. Also have to add the datapath stuff for
PC, etc.
*End: Fri Apr 27 22:20:27 PDT 2001
Approx. total: 1.5 hours
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*Start: Sat Apr 28 11:24:15 PDT 2001
Back to finish the op queue.
I remembered how to figure out the FULL and EMPTY signals - see if HEAD = TAIL, then
check the previous operation. If it was an insert, that means HEAD moved, so the queue
is FULL. If the prev operation was a send, so TAIL moved and the queue is empty.
Starting the op_queue symbol!
*End: Sat Apr 28 13:55:19 PDT 2001
Approx. total: 2.5 hours
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*Start: Sun Apr 29 14:48:56 PDT 2001
Finish making op_queue symbol, and check that I did full/empty signals correctly, then
test whole queue.
A little tricky testing because I found out I was using the old tri state buffer, which
was low-enabled. I switched to the hi-enabled one and then I was getting stuff for
instr_out when I asserted send signal. Oh, and I also forgot to put the squash pin to
the symbol. That signal also affects the empty signal, so I fixed that too.
*End: Sun Apr 29 17:15:31 PDT 2001
Approx. total: 2.5 hours
-----------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------*Start: Wed May 2 14:05:38 PDT 2001
Meeting with group today to talk about stuff.
cache.
I think I'll try and think/start on victim
Ok, now I'm going to work on the integer unit. It takes in 2 32-bit inputs, plus a 5-bit
operation input. The first 3 bits are to specify the operation for the ALU. The last 2
bits enable which output to take: slt, sltu, or the alu.
*End: Wed May
2 17:14:16 PDT 2001
Approx. total: 3 hours
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*Start: Thu May 3 12:43:03 PDT 2001
Going to try and get the lw/sw unit going. I got that done, and so it takes in 2 inputs,
the offset and then the address. It outputs the sum of the sign-extended address with
the address.
*End: Thu May
3 13:56:29 PDT 2001
Approx. total: 1 hours
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*Start: Thu May 3 17:00:13 PDT 2001
I'm going to think about the PC FSM. When to freeze it, etc. So I finally got that
working. I messed up because I put ground incorrectly into the flip flop. So what the
pcwrite symbol does is send hi if the instruction is not jr. If it is, then the pcwrite
will be low, so it can freeze the pc. Only when the go signal is asserted (which will
come from Po's stuff) will the pcwrite signal be asserted.
*End: Thu May
3 20:22:48 PDT 2001
Approx. total: 3 hours
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*Start: Fri May 4 13:35:28 PDT 2001
Koichi needs me to modify the op queue. Now it needs to hold the PC, so I need more 32bit registers. After I finish with that, I'll try and start on the victim cache.
I started to place the some units into the tomasulo datapath, such as mux and reg for PC,
op queue, integer unit, shifter, and lw/sw unit. Now I'm going to make a symbol that
spits out PC+4 and PC+8.
I read a bit about victim caches. They should be fully associative.
look at victim cache. If a hit, swap blocks with cache.
*End: Fri May
When miss in cache,
4 15:47:53 PDT 2001
Approx. total: 2 hours
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*Start: Sat May 5 10:53:36 PDT 2001
I'm reading about victim caches again.
that. Haha, it's in the project spec.
Wondering how big it should be and stuff like
Victim cache'll be 4 cache lines.
(Took 1hr lunch break)
Oh, found an article on 152 page about victim caches. So I should read it.
I added another register to op queue, to hold the
used to see if it's a j, jr, or jal instruction.
write_pc signal, freezing the pc. If it's a j or
address from the pc mux. So I added a j/jal unit
instructions.
*End: Sat May
most recent instruction. This will be
If it's jr, then it should disable the
jal instruction, it will select that
that detects for j and jal
5 20:03:47 PDT 2001
Approx. total: 7.5 hours
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*Start: Tue May 8 17:31:22 PDT 2001
Going to add more stuff to op queue for branch prediction.
each slot and flip-flops also.
Need 32 bit registers for
Took 1hr break.
I added another input for pc to the op_queue. I also tested the tomasulo datapath with
just the pc stuff, op queue, cache and dram. Looks good.
*End: Wed May
9 01:31:44 PDT 2001
Approx. total: 7 hours
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*Start: Wed May 9 11:02:46 PDT 2001
Um, tested the op queue again.
Worked on report, started on presentation slides.
Took 30min break.
*End: Wed May
9 14:47:23 PDT 2001
Approx. total: 3 hours
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*Start: Wed May 9 20:57:01 PDT 2001
Guess I'll work on slides and more of report.
*End: Thu May 10 07:13:38 PDT 2001
Approx. total: 10 hours
-----------------------------------------------------------------------------------------
Koichi Tsunoda
---------------------------------------------------------------------Hours: 4.5
Mon Apr 23 14:00:46 PDT 2001
Met with my group to talk about the details of what we are going to implement.
Mon Apr 23 16:11:11 PDT 2001
We decided on what, and split the work up. I am going to work on the reorder buffer
aspect of our processor.
Mon Apr 23 18:23:00 PDT 2001
Still in the process of designing the reorder buffer.
Total hours so far: 4.5
---------------------------------------------------------------------Hours: 1
Tue Apr 24 12:51:19 PDT 2001
Dropped by to work on the reorder buffer again.
Tue Apr 24 14:00:01 PDT 2001
Still working on the datapath. Finished the Buffer-full logic. Now working on the
datapath that will allow us to add an entry, and commit the instruction.
Class for now.
Total hours so far: 5.5
---------------------------------------------------------------------Hours: 7.5
Tue Apr 24 17:40:00 PDT 2001
Came in. Datapath time.
Wed Apr 25 01:00:55 PDT 2001
Datapath is hard. Lots of issues came up so need to talk about it with members later.
Total hours so far: 13
---------------------------------------------------------------------Hours: 3.75
Wed Apr 25 14:36:59 PDT 2001
Lab time.
Wed Apr 25 18:15:14 PDT 2001
Working on the renaming part. Given the source, I want to be able to give a ROB # if it's
in there. Gotta go for now. Will be back later.
Total hours so far: 16.75
---------------------------------------------------------------------Hours: 5.25
Wed Apr 25 20:44:51 PDT 2001
Came back. Working on the renaming part still.
Wed Apr 25 22:27:19 PDT 2001
Done with the renaming part. Now, I will make a tester for it.
Thu Apr 26 01:56:56 PDT 2001
Woohoo! Got the renaming part working. Done and tested with a testing component. Time to
go home!!!
Total hours so far: 22
---------------------------------------------------------------------Hours: 2
Thu Apr 26 14:01:44 PDT 2001
Starting to work on the ROB again.
Thu Apr 26 16:04:01 PDT 2001
Gotta go for now. Working on the value output for the ROB.
Total hours so far: 24
---------------------------------------------------------------------Hours: 6.5
Thu Apr 26 19:09:59 PDT 2001
Came in with a surprise of MORE things to do for ROB. Yeah. Need to handle stuff for hi
and lo registers.
Fri Apr 27 01:42:43 PDT 2001
Figured out a lot but still not done. Gotta do the controls and talk about the lw unit
with mark later. Think everything else is fine...but not sure...
Total hours so far: 30.5
---------------------------------------------------------------------Hours: 3
Fri Apr 27 14:10:52 PDT 2001
Will start working on the controls for the issuing aspect.
Fri Apr 27 19:41:19 PDT 2001
Food time. Making the symbol for the ROB slots. After this, I can actually work on the
ROB itself. Too many pins!!!
Total hours so far: 33.5
---------------------------------------------------------------------Hours: 1.25
Fri Apr 27 21:07:00 PDT 2001
Back to work!
Fri Apr 27 22:22:11 PDT 2001
Will work on commit controller tomorrow.
Total hours so far: 34.75
---------------------------------------------------------------------Hours: 3
Sat Apr 28 11:08:59 PDT 2001
Back to the lab. Woohoo~. Gotta work on the commit controller.
Sat Apr 28 14:00:31 PDT 2001
Go for now. Now gotta add all the ROB slots into it and make the actual ROB.
Total hours so far: 37.75
---------------------------------------------------------------------Hours: 2
Sat Apr 28 18:31:59 PDT 2001
I will now try to make the actual ROB stuff (with the ROB slots all wired up).
Sat Apr 28 20:27:53 PDT 2001
Blah blah. No. I'm going to worry about the LW/SW stuff more seriously later. I have to
out put RT_VALUE_VALID and RS_VALUE_VALID and I should (that is, SHOULD) be done with the
ROB. So I can start testing. yeah.
Total hours so far: 39.75
---------------------------------------------------------------------Hours: 3.5
Sun Apr 29 14:28:23 PDT 2001
I will add the two signals that I said that I need to add. And then finish up the ROB.
Sun Apr 29 17:05:19 PDT 2001
Got the ROB finished. Now, let me connect the controllers, and then make a testing
component via VHDL.
Sun Apr 29 18:02:11 PDT 2001
I decided that making a testing component for ROB is kind of long and tedious and
annoying. Therefore, I will make a CMD file which will test it. But that's when I come
back next time.
Total hours so far: 43.25
---------------------------------------------------------------------Hours: 4
Wed May 2 14:29:53 PDT 2001
Back to lab. Now going to test ROB.
Wed May 2 18:35:11 PDT 2001
Gotta go for now. But remember to check the CDB_WRITE_VALUE thing. It's writing to all of
it and need to fix it but...weird.
Total hours so far: 47.25
---------------------------------------------------------------------Hours: 3
Wed May 2 21:45:00 PDT 2001
Back. Testing.
Thu May 3 00:49:11 PDT 2001
The integer instruction related stuff seems to be working. I will check the stuff with
multiply tomorrow. I will need to check if the multiply and integer unit finishing at the
same time works too. I will do that tomorrow.
Total hours so far: 50.25
---------------------------------------------------------------------Hours: 1.25
Thu May 3 12:43:12 PDT 2001
More testing.
Thu May
Class!
3 14:00:00 PDT 2001
Total hours so far: 51.5
---------------------------------------------------------------------Hours: 4.75
Thu May 3 17:00:05 PDT 2001
About to start checking the sw/lw related stuff. I still have to do the squishing thing
for the misprediction but I'll take care of it later. For now, I will do this.
Thu May
Food.
3 20:31:33 PDT 2001
Thu May
Back.
3 21:14:55 PDT 2001
Thu May 3 22:36:35 PDT 2001
Got the main things tested. Seems like it's working fine. Still have couple more things
to do. Gotta take care of branch thing and other junks.
Total hours so far: 56.25
---------------------------------------------------------------------Hours: 2
Fri May 4 13:55:33 PDT 2001
I will make a monitor for the final thing right now. Just have to modify the old one we
have to make it work with the new one.
Fri May 4 15:50:11 PDT 2001
Time to stop.
Total hours so far: 58.25
---------------------------------------------------------------------Hours: 7.75
Sat May 5 10:59:59 PDT 2001
Test my monitor.
Sat May 5 11:23:44 PDT 2001
Monitor seems to be fine. Now, I will fix up the Asynch-dram controller.
Sat May
Food
5 12:30:11 PDT 2001
Sat May
Back.
5 13:43:53 PDT 2001
Sat May 5 20:06:21 PDT 2001
Gotta take care of jump instruction. Don't forget. But super-semi-async-dram controller
seems to be fine :)
Total hours so far: 66
---------------------------------------------------------------------Hours: 10
Mon May 7 13:18:55 PDT 2001
I still have to take care of jump, branch, lw in the ROB.
But I will work on the whole tomasulo datapath. I will take what Manda worked on and try
to find out what we're still missing.
Tue May 8 01:37:11 PDT 2001
Think the ROB is pretty much done. We were going to keep the lw seperate from ROB but I
think it's better to add it to the ROB. jump and branch is taken care of now. Wow. 12
hours - time for dinner - time for tv.
Total hours so far: 76
---------------------------------------------------------------------Hours: 1
Tue May 8 12:46:14 PDT 2001
Back to work.
Tue May 8 13:49:33 PDT 2001
Finished the lw related utility. Therefore, I am done. Not. Now I will have to try to put
everything together...figure out what's missing...and then work on that. We MUST get some
instructions running today.
Total hours so far: 77
---------------------------------------------------------------------Hours: 7
Tue May 8 15:32:59 PDT 2001
Back. Will test the lw/sw related unit.
Tue May 8 17:33:19 PDT 2001
Worked on an algorithm which will choose who's going to be issued next. It makes sure
that the oldest one that is available gets issued next. Haven't tested the lw/sw unit
yet. I will test that next perhaps.
Tue May 8 21:27:22 PDT 2001
Got the algorithm for choosing the right instruction to launch done. Now, I will help get
the whole tomasulo thing working.
Tue May 8 21:51:19 PDT 2001
Looking good. Got the memory thing ported.
Tue May 8 23:01:51 PDT 2001
Got the integer related stuff ported.
Tue May 9 01:31:23 PDT 2001
Time to jet for now...
Total hours so far: 84
---------------------------------------------------------------------Hours: .5
Tue May
Back.
9 11:04:32 PDT 2001
Tue May 9 11:43:23 PDT 2001
Eat. Making the JR unit.
Total hours so far: 84.5
---------------------------------------------------------------------Hours: 2.5
Tue May
Back.
9 12:20:11 PDT 2001
Tue May 9 14:50:51 PDT 2001
Commencement.
Total hours so far: 87
---------------------------------------------------------------------Hours:
Tue May 9 18:48:01 PDT 2001
Back. JR again.
Total hours so far:
----------------------------------------------------------------------
Posu Yan
====================================================================
Fri Apr 27 13:57:42 PDT 2001
- starting to make carry look ahead adder
Fri Apr 27 16:02:33 PDT 2001
- starting squasher thing
- revised the algorithm
Fri Apr 27 18:15:26 PDT 2001
- finished the squasher thing
====================================================================
Sat Apr 28 13:28:56 PDT 2001
- slightly modifying squasher
Sat Apr 28 15:07:23 PDT 2001
- starting decode for issuer.. trying to decode everything in parallel
Sat Apr 28 18:54:02 PDT 2001
- finished most of the instruction decodes
====================================================================
Wed May 2 13:34:21 PDT 2001
- going to finish instruction decodes.. not sure about what kind of FSM i need, so i'll
hold off on that
Wed May 2 19:06:10 PDT 2001
- more or less finished decode... not completely sure where jumps, loads are going (their
own station?)
====================================================================
Sat May 5 12:45:24 PDT 2001
- finishing up issuer
Sat May 5 17:18:48 PDT 2001
- pretty much finished with issuer.. not completely sure if i need a state machine in it
tho
- i'll test this tomorrow
====================================================================
Sun May 6 16:44:44 PDT 2001
- starting to do final test of issuer, then finalize the data format
Sun May 6 17:13:05 PDT 2001
- finished testing.. it works, now finalizing data formats
Sun May 6 18:00:52 PDT 2001
- pretty much done, just need to add some more interface signals with ROB
====================================================================
Mon May 7 14:27:42 PDT 2001
- making final changes to issuer
Mon May 7 15:30:56 PDT 2001
- creating vhdl component to output for invalid instructions
Mon May 7 16:37:02 PDT 2001
- finished vhdl complainer component
Mon May 7 17:20:36 PDT 2001
- starting to design CDB arbiter
====================================================================
Mon May 7 18:38:25 PDT 2001
- i think i've got the arbiter FSM structure, it's more high level than the other
arbiter, i think i'll need some higher level comparators and adders
Mon May 7 19:08:42 PDT 2001
- starting to make a one hot adder in vhdl, it should need 16 inputs, but only 8 outputs
Mon May 7 23:58:22 PDT 2001
- finished cdb arbiter, gonna test it tomorrow
====================================================================
Tue May 8 13:15:38 PDT 2001
- starting arbiter testing
Tue May 8 13:36:19 PDT 2001
- arbiter works fine! no bugs at all
- starting to create symbol
Tue May 8 14:02:32 PDT 2001
- arbiter is done!... although may need to add some data muxing, depends on how mark
wants to do it
====================================================================
Tue May 8 17:01:44 PDT 2001
- starting to make lw/sw reservation station unit
Tue May 8 22:12:12 PDT 2001
- this lw/sw thing is much more complicated than i thought... might have to rewrite it
completely
Wed May 9 01:35:12 PDT 2001
- argggggggghhh, i've got most of the datapath for lw/sw.. can't think right now so i'll
do the control tomorrow
====================================================================
Wed May 9 14:04:55 PDT 2001
- starting to make PC fsm... it's much more complicated than we thought
Wed May 9 17:13:12 PDT 2001
- i think i'm finished with the PC fsm.. it's not even an fsm, just a combinational logic
controller
- i'll go back to working on the lw/sw unit
====================================================================
Wed May 9 18:34:51 PDT 2001
- going to need lots of arbiters in the lw/sw unit.. but i have a pretty good idea of how
i'm going to do it
Appendix II – Schematics:
ï‚·
Operation Queue
ï‚·
Reorder Buffer Slot
ï‚·
Reorder Buffer
ï‚·
MultROB
ï‚·
Squasher
ï‚·
ROB Oracle
ï‚·
Address to ROB
ï‚·
Address to ROB Slot
ï‚·
J/JR/JAL Detector Unit
ï‚·
Reservation Station
ï‚·
Common Data Bus Arbiter
ï‚·
Common Data Bus Arbiter FSM
ï‚·
Carry Lookahead Adder
ï‚·
Full Adder
ï‚·
JR Unit
ï‚·
Integer Unit
ï‚·
Squasher
ï‚·
Issuer
ï‚·
PC FSM
ï‚·
Tomasulo Datapath
Appendix III – VHDL Files
Complainer
library pack1076;
use pack1076.pack1076.all;
use std.textio.all;
entity complainer is
port
(clk:
in vlbit;
invalid:
in vlbit);
end complainer;
architecture behavior of complainer is
begin
-- behavior
complainer_process: process
begin
wait until prising(clk);
if (invalid = '1') then
assert false report "invalid instruction!!" severity error;
end if;
end process;
end behavior;
Monitor
library pack1076;
use pack1076.pack1076.all;
use std.textio.all;
entity monitor is
port(signal CLK : in vlbit;
signal INVALIDATE : in vlbit;
signal PC : in vlbit_1d(31 downto 0);
signal INSTRUCTION : in vlbit_1d(31 downto 0);
signal VALUE : in vlbit_1d(31 downto 0);
signal MFHI : in vlbit_1d(31 downto 0);
signal MFLO : in vlbit_1d(31 downto 0);
signal MEM_ADDRESS : in vlbit_1d(31 downto 0));
end monitor;
architecture behavior of monitor is
function vec32tohex(vec: vlbit_1d) return string is
variable str: string(10 downto 1);
variable lo: integer;
variable hi: integer;
begin
for i in 1 to 8 loop
lo := (i-1)*4;
hi := ((i-1)*4)+3;
if(vec(hi downto lo) = "0000") then
str(i) := '0';
elsif(vec(hi downto lo) = "0001") then
str(i) := '1';
elsif(vec(hi downto lo) = "0010") then
str(i) := '2';
elsif(vec(hi downto lo) = "0011") then
str(i) := '3';
elsif(vec(hi downto lo) = "0100") then
str(i) := '4';
elsif(vec(hi downto lo) = "0101") then
str(i) := '5';
elsif(vec(hi downto lo) = "0110") then
str(i) := '6';
elsif(vec(hi downto lo) = "0111") then
str(i) := '7';
elsif(vec(hi downto lo) = "1000") then
str(i) := '8';
elsif(vec(hi downto lo) = "1001") then
str(i) := '9';
elsif(vec(hi downto lo) = "1010") then
str(i) := 'A';
elsif(vec(hi downto lo) = "1011") then
str(i) := 'B';
elsif(vec(hi downto lo) = "1100") then
str(i) := 'C';
elsif(vec(hi downto lo) = "1101") then
str(i) := 'D';
elsif(vec(hi downto lo) = "1110") then
str(i) := 'E';
elsif(vec(hi downto lo) = "1111") then
str(i) := 'F';
else
str(i) := 'X';
end if;
end loop;
str(9) := 'x';
str(10) := '0';
return str;
end;
function vec16tohex(vec: vlbit_1d) return string is
variable str: string(6 downto 1);
variable lo: integer;
variable hi: integer;
begin
for i in 1 to 4 loop
lo := (i-1)*4;
hi := ((i-1)*4)+3;
if(vec(hi downto lo) = "0000") then
str(i) := '0';
elsif(vec(hi downto lo) = "0001") then
str(i) := '1';
elsif(vec(hi downto lo) = "0010") then
str(i) := '2';
elsif(vec(hi downto lo) = "0011") then
str(i) := '3';
elsif(vec(hi downto lo) = "0100") then
str(i) := '4';
elsif(vec(hi downto lo) = "0101") then
str(i) := '5';
elsif(vec(hi downto lo) = "0110") then
str(i) := '6';
elsif(vec(hi downto
str(i) := '7';
elsif(vec(hi downto
str(i) := '8';
elsif(vec(hi downto
str(i) := '9';
elsif(vec(hi downto
str(i) := 'A';
elsif(vec(hi downto
str(i) := 'B';
elsif(vec(hi downto
str(i) := 'C';
elsif(vec(hi downto
str(i) := 'D';
elsif(vec(hi downto
str(i) := 'E';
elsif(vec(hi downto
str(i) := 'F';
else
str(i) := 'X';
end if;
end loop;
str(5) := 'x';
str(6) := '0';
return str;
end;
lo) = "0111") then
lo) = "1000") then
lo) = "1001") then
lo) = "1010") then
lo) = "1011") then
lo) = "1100") then
lo) = "1101") then
lo) = "1110") then
lo) = "1111") then
function vec2intstr(vec: vlbit_1d) return string is
variable stmp: string(2 downto 1);
variable itmp: integer;
begin
itmp := v1d2int(vec);
for i in 1 to 2 loop
case (itmp mod 10) is
when 0 =>
stmp(i downto i) :=
when 1 =>
stmp(i downto i) :=
when 2 =>
stmp(i downto i) :=
when 3 =>
stmp(i downto i) :=
when 4 =>
stmp(i downto i) :=
when 5 =>
stmp(i downto i) :=
when 6 =>
stmp(i downto i) :=
when 7 =>
stmp(i downto i) :=
when 8 =>
stmp(i downto i) :=
when OTHERS =>
stmp(i downto i) :=
end case;
"0";
"1";
"2";
"3";
"4";
"5";
"6";
"7";
"8";
"9";
itmp := itmp / 10;
end loop;
return stmp;
end;
function toString(dumb: string) return string is
begin
return dumb;
end;
begin
monitor:
process
variable
variable
variable
variable
variable
variable
variable
variable
variable
variable
variable
variable
variable
outputLine : line;
opcode : integer;
funct : integer;
destR : string(3 downto 1);
sourceR1 : string(3 downto 1);
sourceR2 : string(3 downto 1);
instr_addr : string(10 downto 1);
destRData : string(10 downto 1);
immed : string(6 downto 1);
shiftAmt : string(2 downto 1);
bz : integer;
mfhiData : string(10 downto 1);
mfloData : string(10 downto 1);
constant
constant
constant
constant
constant
constant
constant
constant
constant
constant
constant
constant
constant
constant
constant
RTYPE_OP : integer := 0;
ADDIU_OP : integer := 9;
LW_OP : integer := 35;
LUI_OP : integer := 15;
SW_OP : integer := 43;
BEQ_OP : integer := 4;
BNE_OP : integer := 5;
BZ_OP : integer := 1;
ANDI_OP : integer := 12;
ORI_OP : integer := 13;
XORI_OP : integer := 14;
SLTI_OP : integer := 10;
SLTIU_OP : integer := 11;
J_OP : integer := 2;
JAL_OP : integer := 3;
constant
constant
constant
constant
constant
constant
constant
constant
constant
constant
constant
constant
constant
constant
ADDU_FUNCT : integer := 33;
SUBU_FUNCT : integer := 35;
AND_FUNCT : integer := 36;
OR_FUNCT : integer := 37;
XOR_FUNCT : integer := 38;
SLL_FUNCT : integer := 0;
SRL_FUNCT : integer := 2;
SRA_FUNCT : integer := 3;
SLT_FUNCT : integer := 42;
SLTU_FUNCT : integer := 43;
JR_FUNCT : integer := 8;
MFHI_FUNCT : integer := 16;
MFLO_FUNCT : integer := 18;
MULTU_FUNCT : integer := 25;
-- for bgez and bltz instructions
constant BGEZ_RT : integer := 1;
constant BLTZ_RT : integer := 0;
begin
wait until pfalling(CLK);
if INVALIDATE = '1' then
opcode := vec2int(INSTRUCTION(31 downto 26));
funct := vec2int(INSTRUCTION(5 downto 0));
instr_addr := vec32tohex(PC);
destRData := vec32tohex(VALUE);
mfhiData := vec32tohex(MFHI);
mfloData := vec32tohex(MFLO);
sourceR1(2 downto 1) := vec2intstr(INSTRUCTION(25 downto 21));
sourceR1(3) := 'r';
write(outputLine, toString(instr_addr & ": "));
case opcode is
when RTYPE_OP =>
sourceR2(2 downto 1) := vec2intstr(INSTRUCTION(20 downto 16));
sourceR2(3) := 'r';
destR(2 downto 1) := vec2intstr(INSTRUCTION(15 downto 11));
destR(3) := 'r';
shiftAmt := vec2intstr(INSTRUCTION(10 downto 6));
case funct is
when ADDU_FUNCT =>
write(outputLine,
write(outputLine,
write(outputLine,
when SUBU_FUNCT =>
write(outputLine,
write(outputLine,
write(outputLine,
when AND_FUNCT =>
write(outputLine,
write(outputLine,
write(outputLine,
when OR_FUNCT =>
write(outputLine,
write(outputLine,
write(outputLine,
when XOR_FUNCT =>
write(outputLine,
write(outputLine,
write(outputLine,
when SLL_FUNCT =>
write(outputLine,
write(outputLine,
write(outputLine,
when SRL_FUNCT =>
write(outputLine,
write(outputLine,
write(outputLine,
when SRA_FUNCT =>
write(outputLine,
write(outputLine,
write(outputLine,
when SLT_FUNCT =>
write(outputLine,
write(outputLine,
write(outputLine,
when SLTU_FUNCT =>
write(outputLine,
write(outputLine,
write(outputLine,
when JR_FUNCT =>
write(outputLine,
write(outputLine,
when MFHI_FUNCT =>
write(outputLine,
write(outputLine,
write(outputLine,
when MFLO_FUNCT =>
write(outputLine,
write(outputLine,
write(outputLine,
when MULTU_FUNCT =>
write(outputLine,
write(outputLine,
write(outputLine,
write(outputLine,
when OTHERS =>
write(outputLine,
end case;
when OTHERS =>
toString("addu "));
toString(destR & "," & sourceR1 & "," & sourceR2));
toString("
R[" & destR & "]=" & destRData));
toString("subu "));
toString(destR & "," & sourceR1 & "," & sourceR2));
toString("
R[" & destR & "]=" & destRData));
toString("and "));
toString(destR & "," & sourceR1 & "," & sourceR2));
toString("
R[" & destR & "]=" & destRData));
toString("or "));
toString(destR & "," & sourceR1 & "," & sourceR2));
toString("
R[" & destR & "]=" & destRData));
toString("xor "));
toString(destR & "," & sourceR1 & "," & sourceR2));
toString("
R[" & destR & "]=" & destRData));
toString("sll "));
toString(destR & "," & sourceR2 & "," & shiftAmt));
toString("
R[" & destR & "]=" & destRData));
toString("srl "));
toString(destR & "," & sourceR2 & "," & shiftAmt));
toString("
R[" & destR & "]=" & destRData));
toString("sra "));
toString(destR & "," & sourceR2 & "," & shiftAmt));
toString("
R[" & destR & "]=" & destRData));
toString("slt "));
toString(destR & "," & sourceR1 & "," & sourceR2));
toString("
R[" & destR & "]=" & destRData));
toString("sltu "));
toString(destR & "," & sourceR1 & "," & sourceR2));
toString("
R[" & destR & "]=" & destRData));
toString("jr "));
toString(sourceR1));
toString("mfhi "));
toString(destR));
toString("
R[" & destR & "]=" & destRData));
toString("mflo "));
toString(destR));
toString("
R[" & destR & "]=" & destRData));
toString("multu "));
toString(sourceR1 & "," & sourceR2));
toString("
HI=" & mfhiData));
toString(", LO=" & mfloData));
toString("UNKNOWN FUNCT"));
destR(2 downto 1) := vec2intstr(INSTRUCTION(20 downto 16));
destR(3 downto 3) := "r";
immed := vec16tohex(INSTRUCTION(15 downto 0));
case opcode is
when ADDIU_OP =>
write(outputLine, toString("addiu "));
write(outputLine, toString(destR & "," & sourceR1 & "," & immed));
write(outputLine, toString(" R[" & destR & "]=" & destRData));
when ANDI_OP =>
write(outputLine, toString("andi "));
write(outputLine, toString(destR & "," & sourceR1 & "," & immed));
write(outputLine, toString("
R[" & destR & "]=" & destRData));
when XORI_OP =>
write(outputLine, toString("xori "));
write(outputLine, toString(destR & "," & sourceR1 & "," & immed));
write(outputLine, toString("
R[" & destR & "]=" & destRData));
when ORI_OP =>
write(outputLine, toString("ori "));
write(outputLine, toString(destR & "," & sourceR1 & "," & immed));
write(outputLine, toString("
R[" & destR & "]=" & destRData));
when LW_OP =>
write(outputLine, toString("lw "));
write(outputLine, toString(destR & "," & immed & "(" & sourceR1 & ")"));
write(outputLine, toString("
R[" & destR & "]=" & destRData));
when LUI_OP =>
write(outputLine, toString("lui "));
write(outputLine, toString(destR & "," & immed));
write(outputLine, toString("
R[" & destR & "]=" & destRData));
when SW_OP =>
write(outputLine, toString("sw "));
write(outputLine, toString(destR & "," & immed & "(" & sourceR1 & ")"));
write(outputLine, toString("
MEM[" & vec32tohex(MEM_ADDRESS) & "]=" &
destRData));
when BEQ_OP =>
write(outputLine, toString("beq "));
write(outputLine, toString(destR & "," & sourceR1 & "," & immed));
when BNE_OP =>
write(outputLine, toString("bne "));
write(outputLine, toString(destR & "," & sourceR1 & "," & immed));
when BZ_OP =>
bz := v1d2int(INSTRUCTION(20 downto 16));
destR(2 downto 1) := vec2intstr(INSTRUCTION(25 downto 21));
case bz is
when BGEZ_RT =>
write(outputLine, toString("bgez "));
write(outputLine, toString(destR & "," & immed));
when BLTZ_RT =>
write(outputLine, toString("bltz "));
write(outputLine, toString(destR & "," & immed));
when OTHERS =>
write(outputLine, toString("UNKNOWN BRANCH INSTR"));
end case;
when SLTI_OP =>
write(outputLine, toString("slti "));
write(outputLine, toString(destR & "," & sourceR1 & "," & immed));
write(outputLine, toString("
R[" & destR & "]=" & destRData));
when SLTIU_OP =>
write(outputLine, toString("sltiu "));
write(outputLine, toString(destR & "," & sourceR1 & "," & immed));
write(outputLine, toString(" R[" & destR & "]=" & destRData));
when J_OP =>
immed := vec16tohex(INSTRUCTION(25 downto 0));
write(outputLine, toString("j "));
write(outputLine, toString(immed));
when JAL_OP =>
immed := vec16tohex(INSTRUCTION(25 downto 0));
write(outputLine, toString("jal "));
write(outputLine, toString(immed));
when OTHERS =>
write(outputLine, toString("UNKNOWN OPCODE"));
end case;
end case;
writeline(output, outputLine);
end if;
end process;
end behavior;
Renamer
library pack1076;
use pack1076.pack1076.all;
entity renamer is
port(signal DIN:
signal DOUT:
end renamer;
in
out
vlbit;
vlbit);
architecture behavior of renamer is
begin
renamer : process(DIN)
begin
DOUT <= DIN;
end process renamer;
end behavior;
ROB Issue Controller
library pack1076;
use pack1076.pack1076.all;
entity rob_issue_controller is
generic (delay: TIME := 1 ns);
-- for now
port(signal INSTR_TYPE : in vlbit_1d(5 downto 0);
signal ISSUE_INSTR : in vlbit;
signal NOT_SUPPLEMENTARY_DATA_READY : out vlbit;
signal INSTRUCTION_TYPE : out vlbit_1d(4 downto 0);
signal ISSUE_ADDRESS_CALC : out vlbit);
end rob_issue_controller;
architecture behavior of rob_issue_controller is
begin
rob_issue_controller_process: process(INSTR_TYPE, ISSUE_INSTR)
constant swOp : integer := 1;
constant lwOp : integer := 2;
constant regOp : integer := 4;
constant branchOp : integer := 8;
constant multOp : integer := 16;
constant jJrOp : integer := 32;
begin
if ISSUE_INSTR = '1' then
case v1d2int(INSTR_TYPE) is
when swOP =>
NOT_SUPPLEMENTARY_DATA_READY <= '1' after
INSTRUCTION_TYPE <= "00010" after delay;
ISSUE_ADDRESS_CALC <= '1' after delay;
when lwOp =>
NOT_SUPPLEMENTARY_DATA_READY <= '0' after
INSTRUCTION_TYPE <= "00100" after delay;
ISSUE_ADDRESS_CALC <= '1' after delay;
when regOp =>
NOT_SUPPLEMENTARY_DATA_READY <= '0' after
INSTRUCTION_TYPE <= "00100" after delay;
ISSUE_ADDRESS_CALC <= '0' after delay;
when branchOp =>
NOT_SUPPLEMENTARY_DATA_READY <= '0' after
INSTRUCTION_TYPE <= "00001" after delay;
ISSUE_ADDRESS_CALC <= '0' after delay;
when multOp =>
NOT_SUPPLEMENTARY_DATA_READY <= '0' after
delay;
delay;
delay;
delay;
delay;
INSTRUCTION_TYPE <= "01000" after delay;
ISSUE_ADDRESS_CALC <= '0' after delay;
when jJrOp =>
NOT_SUPPLEMENTARY_DATA_READY <= '0' after delay;
INSTRUCTION_TYPE <= "10000" after delay;
ISSUE_ADDRESS_CALC <= '0' after delay;
when others =>
null;
end case;
else
NOT_SUPPLEMENTARY_DATA_READY <= '1' after delay;
INSTRUCTION_TYPE <= "00001" after delay;
ISSUE_ADDRESS_CALC <= '0' after delay;
end if;
--
when jrFunct =>
end process;
end behavior;
ROB Commit Controller
library pack1076;
use pack1076.pack1076.all;
entity rob_commit_controller is
generic (delay: TIME := 1 ns);
-- for now
port(signal INSTR_TYPE : in vlbit_1d(4 downto 0);
signal COMMIT : in vlbit;
signal STALL : in vlbit;
signal INVALIDATE : out vlbit;
signal REG_WRITE : out vlbit;
signal MEM_WRITE : out vlbit;
signal MULT_REG_WRITE : out vlbit);
end rob_commit_controller;
architecture behavior of rob_commit_controller is
begin
rob_commit_controller_process: process(INSTR_TYPE, COMMIT, STALL)
constant branchOp : integer := 1;
constant swOp : integer := 2;
constant regOp : integer := 4;
constant multOp : integer := 8;
constant jJrOp : integer := 16;
begin
if COMMIT = '1' then
case v1d2int(INSTR_TYPE) is
when swOP =>
if (STALL = '1') then
INVALIDATE <= '0' after delay;
else
INVALIDATE <= '1' after delay;
end if;
REG_WRITE <= '0' after delay;
MEM_WRITE <= '1' after delay;
MULT_REG_WRITE <= '0' after delay;
when regOp =>
INVALIDATE <= '1' after delay;
REG_WRITE <= '1' after delay;
MEM_WRITE <= '0' after delay;
MULT_REG_WRITE <= '0' after delay;
when branchOp =>
INVALIDATE <= '1' after delay;
REG_WRITE <= '0' after delay;
MEM_WRITE <= '0' after delay;
MULT_REG_WRITE <= '0' after delay;
when multOp =>
INVALIDATE <= '1' after delay;
REG_WRITE <= '0' after delay;
MEM_WRITE <= '0' after delay;
MULT_REG_WRITE <= '1' after delay;
when jJrOp =>
INVALIDATE <= '1' after delay;
REG_WRITE <= '0' after delay;
MEM_WRITE <= '0' after delay;
MULT_REG_WRITE <= '0' after delay;
when others =>
null;
end case;
else
INVALIDATE <= '0' after delay;
REG_WRITE <= '0' after delay;
MEM_WRITE <= '0' after delay;
MULT_REG_WRITE <= '0' after delay;
end if;
end process;
end behavior;
Reservation Station ALU Issuer
--------------------------------------------------------------------------------This is the Controller for the Reservation Stations
------------------------------------------------------------------------------library pack1076;
use pack1076.pack1076.all;
entity RSctrlALUI is
generic (delay: time := 6 ns);
port(
--Also add
signal
signal
signal
signal
--we'll probably have to change this
inputs to account for the instruction broadcasts.
CLK : in vlbit;
issue : in vlbit;
instr : in vlbit_1d(84 downto 0);
taken : in vlbit_1d(15 downto 0);
signal listen : out vlbit_1d(3 downto 0);
signal full : out vlbit
);
end RSctrlALUI;
architecture behavior of RSctrlALUI is
-- purpose: to loop-increment next_issue
function inc(x: integer) return integer is
begin -- inc
if (x = 15) then
return 0;
elsif (x < 0) then
return -1;
elsif (x > 15) then
return -1;
else
return (x + 1);
end if;
end inc;
function vlbit_1dtoint(input : vlbit_1d) return integer is
variable x : vlbit_1d(3 downto 0) := input;
variable y : integer;
begin
case x is
when "0000" =>
y := 0;
when "0001" =>
y := 1;
when "0010"
y := 2;
when "0011"
y := 3;
when "0100"
y := 4;
when "0101"
y := 5;
when "0110"
y := 6;
when "0111"
y := 7;
when "1000"
y := 8;
when "1001"
y := 9;
when "1010"
y := 10;
when "1011"
y := 11;
when "1100"
y := 12;
when "1101"
y := 13;
when "1110"
y := 14;
when "1111"
y := 15;
when others
y := -1;
end case;
return y;
end;
=>
=>
=>
=>
=>
=>
=>
=>
=>
=>
=>
=>
=>
=>
=>
function inttovlbit_1d(x : integer) return vlbit_1d is
variable y : vlbit_1d(3 downto 0);
begin
case x is
when 0 =>
y := "0000";
when 1 =>
y := "0001";
when 2 =>
y := "0010";
when 3 =>
y := "0011";
when 4 =>
y := "0100";
when 5 =>
y := "0101";
when 6 =>
y := "0110";
when 7 =>
y := "0111";
when 8 =>
y := "1000";
when 9 =>
y := "1001";
when 10 =>
y := "1010";
when 11 =>
y := "1011";
when 12 =>
y := "1100";
when 13 =>
y := "1101";
when 14 =>
y := "1110";
when 15 =>
y := "1111";
when others =>
y := "XXXX";
end case;
return y;
end;
begin
RSctrlALUI:process
constant numStations : integer := 16;
variable next_issue : integer := 1;
variable count : integer := 0;
variable keepLooping : boolean := true;
variable stationsOccupied : vlbit_1d((numStations - 1) downto 0);
variable initialSetupDone : boolean := false;
--This is where everything REALLY begins
begin
if not initialSetupDone then
listen <= "0000";
initialSetupDone := true;
end if;
wait until pfalling(CLK);
-- just remember that this actually calculates the NEXT reservation that it
-- needs to listen to. this avoids the glitch problem in the issue. it will
-- only check the issue signal at the falling edge, and use the current one
-- for the reservation station, and have the next one calculated.
if (issue = '1') then
count := 0;
keepLooping := true;
while ((count < numStations) and (keepLooping = true)) loop
if (taken(next_issue) = '1') then
next_issue := inc(next_issue);
else
listen <= inttovlbit_1d(next_issue) after delay;
keepLooping := false;
next_issue := inc(next_issue);
end if;
count := count + 1;
end loop;
end if;
if (taken
full <=
else
full <=
end if;
end process
end behavior;
= "1111111111111111") then
'1' after delay;
'0' after delay;
RSctrlALUI;
Reservation Station ALU Launcher
--------------------------------------------------------------------------------This is the Controller for the Reservation Stations
------------------------------------------------------------------------------library pack1076;
use pack1076.pack1076.all;
use std.textio.all;
entity RSctrlALUL is
generic (delay: time := 6 ns);
port(
--Also add
signal
signal
signal
signal
signal
signal
--we'll probably have to change this
inputs to account for the instruction broadcasts.
CLK : in vlbit;
taken : in vlbit_1d(15 downto 0);
notReady : in vlbit_1d(15 downto 0);
granted : in vlbit;
busy : in vlbit_1d(15 downto 0);
squish : in vlbit;
signal toFU : out vlbit_1d(3 downto 0);
signal CDBreq : out vlbit;
signal resetRS : out vlbit_1d(3 downto 0
);
signal issue : in vlbit;
signal listen : in vlbit_1d(3 downto 0)
);
end RSctrlALUL;
architecture behavior of RSctrlALUL is
function toString(dumb: string) return string is
begin
return dumb;
end;
-- purpose: to loop-increment next_issue
function inc(x: integer) return integer is
begin -- inc
if (x = 15) then
return 0;
elsif (x < 0) then
return -1;
elsif (x > 15) then
return -1;
else
return (x + 1);
end if;
end inc;
function vlbit_1dtoint(input : vlbit_1d) return integer is
variable x : vlbit_1d(3 downto 0) := input;
variable y : integer;
begin
case x is
when "0000" =>
y := 0;
when "0001" =>
y := 1;
when "0010" =>
y := 2;
when "0011" =>
y := 3;
when "0100" =>
y := 4;
when "0101" =>
y := 5;
when "0110" =>
y := 6;
when "0111" =>
y := 7;
when "1000" =>
y := 8;
when "1001" =>
y := 9;
when "1010" =>
y := 10;
when "1011" =>
y := 11;
when "1100" =>
y := 12;
when "1101" =>
y := 13;
when "1110" =>
y := 14;
when "1111" =>
y := 15;
when others =>
y := -1;
end case;
return y;
end;
function inttovlbit_1d(x : integer) return vlbit_1d is
variable y : vlbit_1d(3 downto 0);
begin
case x is
when 0 =>
y := "0000";
when 1 =>
y := "0001";
when 2 =>
y := "0010";
when 3 =>
y := "0011";
when 4 =>
y := "0100";
when 5 =>
y := "0101";
when 6 =>
y := "0110";
when 7 =>
y := "0111";
when 8 =>
y := "1000";
when 9 =>
y := "1001";
when 10 =>
y := "1010";
when 11 =>
y := "1011";
when 12 =>
y := "1100";
when 13 =>
y := "1101";
when 14 =>
y := "1110";
when 15 =>
y := "1111";
when others =>
y := "XXXX";
end case;
return y;
end;
constant numOfStations : integer := 16;
type queue is array((numOfStations-1) downto 0) of integer;
-- initialized so that queue has not duplicates;
-- lowest address is next to be evicted
begin
RSctrlALUL:process
variable stationsNotReady : vlbit_1d((numOfStations - 1) downto 0);
variable stationsTaken : vlbit_1d((numOfStations - 1) downto 0);
variable stationsBusy : vlbit_1d((numOfStations - 1) downto 0);
variable count : integer := 0;
variable launchNum : integer := 0;
variable keepLooping : boolean := true;
variable justRequestedCDB : boolean := false;
variable requestedLongAgo : boolean := false;
variable outputline : line;
variable lastLaunched : integer := -1;
variable oldestInstr : integer := 0;
variable execQueue : queue;
variable initSetupDone : boolean := false;
variable numIssued : integer;
variable issueInQueue : boolean;
variable tempCounter : integer;
--This is where everything REALLY begins
begin
if not initSetupDone then
for i in 0 to numOfStations - 1 loop
execQueue(i) := -1;
end loop; -- i
initSetupDone := true;
end if;
wait until pfalling(CLK);
--latch a few key values
if ISSUE = '1' then
-- check and see if the LISTEN is already in the queue or not.
numIssued := v1d2int(LISTEN);
issueInQueue := false;
for i in 0 to numOfStations - 1 loop
if execQueue(i) = numIssued then
issueInQueue := true;
end if;
end loop; -- i
if not issueInQueue then
-- it was not in the queue so add it to the queue.
tempCounter := 0;
while not issueInQueue loop
if execQueue(tempCounter) = -1 then
execQueue(tempCounter) := numIssued;
issueInQueue := true;
else
tempCounter := tempCounter + 1;
assert tempCounter < numOfStations report "something is wrong in the
RSctrlALUL" severity error;
end if;
end loop;
else
assert false report "this means that something that has been issued is being
issued again. obviously an error." severity error;
end if;
end if;
stationsNotReady := notReady(15 downto 0);
stationsTaken := taken(15 downto 0);
stationsBusy := busy(15 downto 0);
keepLooping := true;
if ((requestedLongAgo = true) and (granted = '0')) then
-- Do this if you requested, but weren't granted
CDBreq <= '1' after delay;
requestedLongAgo := justRequestedCDB;
justRequestedCDB := true;
else
tempCounter := -1;
keepLooping := true;
while tempCounter < 15 and keepLooping loop
tempCounter := tempCounter + 1;
launchNum := execQueue(tempCounter);
if launchNum /= -1 then
if((stationsTaken(launchNum) = '1')
and (stationsNotReady(launchNum) = '0')
and (stationsBusy(launchNum) = '0')
and (squish /= '1')) then
keepLooping := false;
end if;
else
keepLooping := false;
end if;
end loop;
-- at this point, if the launchNum is -1, that means nothing can be
-- launched cause it is not ready.
if launchNum /= -1 then
-- now, get rid of the station that has been just launched from the
-- queue. the station to be launched is # tempCounter.
if tempCounter <= numOfStations - 2 then
for i in tempCounter to numOfStations - 2 loop
execQueue(i) := execQueue(i+1);
end loop; -- i
end if;
execQueue(numOfStations-1) := -1;
toFU <= inttovlbit_1d(launchNum) after delay;
CDBreq <= '1' after delay;
requestedLongAgo := justRequestedCDB;
resetRS <= inttovlbit_1d(lastLaunched) after delay;
lastLaunched := launchNum;
justRequestedCDB := true;
--write(outputline, launchNum);
--write(outputline, toString(" is the RS we're choosing to launch "));
--writeline(output, outputline);
else
--write(outputline, toString("Nothing to launch"));
--writeline(output, outputline);
CDBreq <= '0' after delay;
requestedLongAgo := justRequestedCDB;
justRequestedCDB := false;
end if;
end if;
end process RSctrlALUL;
end behavior;
Tri-state Buffer Low Enable
library pack1076;
use pack1076.pack1076.all;
entity bts4x32 is
generic (
delay: time:= 1 ns
);
port (
T_L:
DIN:
DOUT:
);
end bts4x32;
in vlbit;
in vlbit_1d (31 downto 0);
out vlbit_1d (31 downto 0)
architecture behavior of bts4x32 is
begin -- behavior
bts4x32_process: process (T_L, DIN)
begin
if (T_L = '1') then
DOUT <= "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" after delay;
else
DOUT <= DIN (31 downto 0) after delay;
end if;
end process;
end behavior;
Tri-state Buffer High Enable
library pack1076;
use pack1076.pack1076.all;
entity bts4x32_h is
generic (
delay: time:= 1 ns
);
port (
T_H:
DIN:
DOUT:
);
end bts4x32_h;
in vlbit;
in vlbit_1d (31 downto 0);
out vlbit_1d (31 downto 0)
architecture behavior of bts4x32_h is
begin -- behavior
bts4x32_process: process (T_H, DIN)
begin
if (T_H = '0') then
DOUT <= "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" after delay;
else
DOUT <= DIN (31 downto 0) after delay;
end if;
end process;
end behavior;
One Hot Adder
library pack1076;
use pack1076.pack1076.all;
entity oha16 is
generic(delay: TIME := 2 ns);
port
(i:
in vlbit_1d(15 downto 0);
o0: out vlbit;
o1: out vlbit;
o2: out vlbit;
o3: out vlbit;
o4: out vlbit;
o5: out vlbit;
o6: out vlbit;
o7: out vlbit);
end oha16;
architecture behavior of oha16 is
begin
oha16_process:
variable sum
variable ot0
variable ot1
variable ot2
variable ot3
variable ot4
variable ot5
variable ot6
variable ot7
begin
sum := 0;
ot0 := '0';
ot1 := '0';
ot2 := '0';
ot3 := '0';
ot4 := '0';
ot5 := '0';
ot6 := '0';
ot7 := '0';
:
:
:
:
:
:
:
:
:
process(i)
integer := 0;
vlbit := '0';
vlbit := '0';
vlbit := '0';
vlbit := '0';
vlbit := '0';
vlbit := '0';
vlbit := '0';
vlbit := '0';
-- process
for junk in 0 to 15 loop
sum := sum + vlb2int(i(junk));
end loop; -- junk
case sum is
when 0 =>
ot0 := '1';
when 1 =>
ot1 := '1';
when 2 =>
ot2 := '1';
when 3 =>
ot3 := '1';
when 4 =>
ot4 := '1';
when 5 =>
ot5 := '1';
when 6 =>
-- behavior
ot6 := '1';
when 7 =>
ot7 := '1';
when others => null;
end case;
o0 <= ot0 after
o1 <= ot1 after
o2 <= ot2 after
o3 <= ot3 after
o4 <= ot4 after
o5 <= ot5 after
o6 <= ot6 after
o7 <= ot7 after
end process;
end behavior;
delay;
delay;
delay;
delay;
delay;
delay;
delay;
delay;
In Out Test
library pack1076;
use pack1076.pack1076.all;
use std.textio.all;
entity inout_test is
generic (
delay : time := 6 ns);
port (
--Interface to Pipeline
signal clk : in vlbit;
signal r_w : in vlbit;
--1 when processor is doing a write
signal d_ioo : inout vlbit_1d(31 downto 0);
signal d_ioe : inout vlbit_1d(31 downto 0);
signal d64out : out vlbit_1d(63 downto 0));
end inout_test;
architecture behavior of inout_test is
function toString(dumb: string) return string is
begin
return dumb;
end;
function vec32tohex(vec: vlbit_1d; inlo:integer) return string is
variable str: string(8 downto 1);
variable lo: integer;
variable hi: integer;
begin
for i in 1 to 8 loop
lo := inlo+(i-1)*4;
hi := inlo+((i-1)*4)+3;
if(vec(hi downto lo) = "0000") then
str(i) := '0';
elsif(vec(hi downto lo) = "0001") then
str(i) := '1';
elsif(vec(hi downto lo) = "0010") then
str(i) := '2';
elsif(vec(hi downto lo) = "0011") then
str(i) := '3';
elsif(vec(hi downto lo) = "0100") then
str(i) := '4';
elsif(vec(hi downto lo) = "0101") then
str(i) := '5';
elsif(vec(hi downto lo) = "0110") then
str(i) := '6';
elsif(vec(hi downto lo) = "0111") then
str(i) := '7';
elsif(vec(hi downto lo) = "1000") then
str(i) := '8';
elsif(vec(hi downto lo) = "1001") then
str(i) := '9';
elsif(vec(hi downto lo) = "1010")
str(i) := 'A';
elsif(vec(hi downto lo) = "1011")
str(i) := 'B';
elsif(vec(hi downto lo) = "1100")
str(i) := 'C';
elsif(vec(hi downto lo) = "1101")
str(i) := 'D';
elsif(vec(hi downto lo) = "1110")
str(i) := 'E';
elsif(vec(hi downto lo) = "1111")
str(i) := 'F';
elsif((vec(hi downto hi) = "X")
or (vec(hi-1 downto hi-1) =
or (vec(hi-2 downto hi-2) =
or (vec(hi-3 downto hi-3) =
str(i) := 'X';
else
str(i) := 'Z';
end if;
end loop;
return str;
end;
begin
then
then
then
then
then
then
"X")
"X")
"X")) then
-- behavior
inout_test: process
variable d64in : vlbit_1d(63 downto 0);
begin
wait until pfalling(clk);
if r_w = '1' then
wait for 5 ns;
d_ioo <= "11111111111111111111111111111111";
d_ioe <= "01010101010101010101010101010101";
wait for 5 ns;
else
wait for 5 ns;
d64in(63 downto 32) := d_ioo;
d64in(31 downto 0) := d_ioe;
d64out <= d64in after delay;
wait for 5 ns;
end if;
d_ioo <= "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ";
d_ioe <= "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ";
wait for 5 ns;
end process;
end behavior;
Memory Control
library pack1076;
use pack1076.pack1076.all;
use std.textio.all;
entity mc is
generic (
delay : time := 6 ns;
long_delay : time := 12 ns;
freaking_long_delay : time := 31 ns);
port (
--Interface to Pipeline
signal c : in vlbit;
signal req : in vlbit;
--1 when processor making req
signal r_w : in vlbit;
--1 when processor is doing a write
signal d_in : in vlbit_1d(63 downto 0);
signal ad : in vlbit_1d(9 downto 0);
signal d_out : out vlbit_1d(63 downto 0);
signal w_h : out vlbit;
--Interface to DRAM Controller
signal d_ioo : inout vlbit_1d(31 downto 0);
signal d_ioe : inout vlbit_1d(31 downto 0);
signal a_oo : out vlbit_1d(4 downto 0);
signal a_oe : out vlbit_1d(4 downto 0);
signal RAS_L : out vlbit;
signal CAS_L : out vlbit;
signal OE_L : out vlbit;
signal WE_L : out vlbit;
signal REF_L : out vlbit;
signal S : in vlbit);
end mc;
architecture behavior of mc is
function toString(dumb: string) return string is
begin
return dumb;
end;
function vec32tohex(vec: vlbit_1d; inlo:integer) return string is
variable str: string(8 downto 1);
variable lo: integer;
variable hi: integer;
begin
for i in 1 to 8 loop
lo := inlo+(i-1)*4;
hi := inlo+((i-1)*4)+3;
if(vec(hi downto lo) = "0000") then
str(i) := '0';
elsif(vec(hi downto lo) = "0001") then
str(i) := '1';
elsif(vec(hi downto lo) = "0010") then
str(i) := '2';
elsif(vec(hi downto lo) = "0011") then
str(i) := '3';
elsif(vec(hi downto lo) = "0100") then
str(i) := '4';
elsif(vec(hi downto lo) = "0101") then
str(i) := '5';
elsif(vec(hi downto lo) = "0110") then
str(i) := '6';
elsif(vec(hi downto lo) = "0111") then
str(i) := '7';
elsif(vec(hi downto lo) = "1000") then
str(i) := '8';
elsif(vec(hi downto lo) = "1001") then
str(i) := '9';
elsif(vec(hi downto lo) = "1010") then
str(i) := 'A';
elsif(vec(hi downto lo) = "1011") then
str(i) := 'B';
elsif(vec(hi downto lo) = "1100") then
str(i) := 'C';
elsif(vec(hi downto lo) = "1101") then
str(i) := 'D';
elsif(vec(hi downto lo) = "1110") then
str(i) := 'E';
elsif(vec(hi downto lo) = "1111") then
str(i) := 'F';
elsif((vec(hi downto hi) = "X")
or (vec(hi-1 downto hi-1) = "X")
or (vec(hi-2 downto hi-2) = "X")
or (vec(hi-3 downto hi-3) = "X")) then
str(i) := 'X';
else
str(i) := 'Z';
end if;
end loop;
return str;
end;
begin
-- behavior
mc: process
variable outputline : line;
variable addr : vlbit_1d(9 downto 0);
variable startingup : boolean := true;
variable storedD_in : vlbit_1d(63 downto 0);
variable delay_1 : time;
variable delay_2 : time;
variable delay_2p1 : time;
variable ras_high_time : time;
variable ras_precharge_time : time;
variable wait_time : time;
variable time_to_wait : time;
constant X32 : vlbit_1d := "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
constant X64 : vlbit_1d :=
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
constant wait_prop_delay : time := 10 ns;
variable cycle_time : time;
variable last_clock_time : time;
variable cycle_read_done : integer;
variable cycle_write_done : integer;
variable temp_time : time;
variable r_done_time : time;
variable w_done_time : time;
variable r_wait_cause_of_prop : time;
variable w_wait_cause_of_prop : time;
begin
wait until pfalling(c);
if (startingup = true) then
RAS_L <= '1';
CAS_L <= '1';
OE_L <= '1';
WE_L <= '1';
w_h <= '1';
ras_high_time := now;
last_clock_time := now;
wait until pfalling(c);
cycle_time := now - last_clock_time;
----
if S = '1' then
delay_1 := 95 ns;
delay_2 := 120 ns;
delay_2p1 := 121 ns;
ras_precharge_time := 195 ns;
r_done_time := 227 ns;
w_done_time := 225 ns;
else
delay_1 := 21 ns;
delay_2 := 30 ns;
delay_2p1 := 31 ns;
ras_precharge_time := 45 ns;
r_done_time := 63 ns;
w_done_time := 61 ns;
end if;
write(outputline, cycle_time);
write(outputline, toString(" is the cycle time."));
writeline(output, outputline);
startingup := false;
end if;
REF_L <= '1';
--change this later
if (req = '1') then
--have a request
-----------
---
wait_time := now - ras_high_time;
w_h <= '1';
write(outputline, now);
write(outputline, toString(" is now. "));
write(outputline, wait_time);
write(outputline, toString(" is time i waited. "));
write(outputline, ras_high_time);
write(outputline, toString(" is the last time RAS went high."));
writeline(output, outputline);
if wait_time < ras_precharge_time then
write(outputline, toString("Precharge time not met so will have to wait "));
time_to_wait := ras_precharge_time - wait_time;
write(outputline, time_to_wait);
writeline(output, outputline);
wait for time_to_wait;
else
time_to_wait := 0 ns;
write(outputline, toString("Precharge time met so will not have to wait"));
writeline(output, outputline);
end if;
-- find the time this must wait later on. don't ask what it does unless
-- you REALLY want to know cause it's kind of crazy.
temp_time := 0 ns;
cycle_read_done := 0;
while temp_time < r_done_time + time_to_wait loop
temp_time := temp_time + cycle_time;
cycle_read_done := cycle_read_done + 1;
end loop;
temp_time := 0 ns;
cycle_write_done := 0;
while temp_time < w_done_time + time_to_wait loop
temp_time := temp_time + cycle_time;
cycle_write_done := cycle_write_done + 1;
end loop;
temp_time := temp_time - (w_done_time + time_to_wait);
if temp_time < wait_prop_delay then
w_wait_cause_of_prop := temp_time;
else
w_wait_cause_of_prop := 0 ns;
end if;
temp_time := cycle_read_done * cycle_time - (r_done_time + time_to_wait);
if temp_time < wait_prop_delay then
r_wait_cause_of_prop := temp_time;
else
r_wait_cause_of_prop := 0 ns;
end if;
-write(outputline,
-write(outputline,
-writeline(output,
-write(outputline,
-write(outputline,
-writeline(output,
-write(outputline,
-write(outputline,
time."));
-writeline(output,
-write(outputline,
-write(outputline,
time."));
-writeline(output,
cycle_write_done);
toString(" is the cycle write is going to finish."));
outputline);
cycle_read_done);
toString(" is the cycle read is going to finish."));
outputline);
r_wait_cause_of_prop);
toString(" is the time needed for the wait to have enough
outputline);
w_wait_cause_of_prop);
toString(" is the time needed for the wait to have enough
outputline);
if (r_w = '1') then
addr := ad;
storedD_in := d_in;
d_out <= X64;
a_oo <= addr(9 downto 5);
a_oe <= addr(9 downto 5);
d_ioo <= X32;
--a write
d_ioe <= X32;
wait for 5 ns;
RAS_L <= '0';
wait for delay_1;
a_oo(4 downto 1) <= addr(4 downto 1);
a_oo(0) <= '1';
a_oe(4 downto 1) <= addr(4 downto 1);
a_oe(0) <= '0';
d_ioo <= storedD_in(63 downto 32);
d_ioe <= storedD_in(31 downto 0);
WE_L <= '0';
wait for 5 ns;
CAS_L <= '0';
wait for delay_2;
wait for w_wait_cause_of_prop;
-- RAS go high now 60/225 ns later. The
-- 40/175 ns. But the precharge time of
else
--A read
addr := ad;
d_out <= X64;
a_oo <= addr(9 downto 5);
a_oe <= addr(9 downto 5);
wait for 5 ns;
RAS_L <= '0';
wait for delay_1;
a_oo(4 downto 1) <= addr(4 downto 1);
a_oo(0) <= '1';
a_oe(4 downto 1) <= addr(4 downto 1);
a_oe(0) <= '0';
OE_L <= '0';
wait for 5 ns;
CAS_L <= '0';
wait for delay_2p1;
d_out(63 downto 32) <= d_ioo;
d_out(31 downto 0) <= d_ioe;
wait for 1 ns;
wait for r_wait_cause_of_prop;
-- RAS go high now 62/227 ns later. The
-- 38/173 ns. But the precharge time of
end if;
ras_high_time := now;
end if;
RAS must not go down for at least
50/200 ns must be met as well.
RAS must not go down for at least
50/200 ns must be met as well.
-- I will make the wait go low right now so that the processor can go do whatever
-- it needs to do. But if a request comes before the precharge time is met,
-- it'll need to take care of it by doing some wait before the RAS goes
-- down low again. So we keep the "now" time to do that calculation later.
CAS_L <= '1';
RAS_L <= '1';
WE_L <= '1';
OE_L <= '1';
w_h <= '0';
d_ioo <= X32;
d_ioe <= X32;
a_oo <= "XXXXX";
a_oe <= "XXXXX";
d_ioo <= "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ";
d_ioe <= "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ";
end process;
end behavior;
Source to ROB Tester
------------------------------------------------- source2rob test bench version 3.1415926535897
-----------------------------------------------library pack1076;
use pack1076.pack1076.all;
library ieee;
use std.textio.all;
entity source2rob_tester is
generic (
delay
: time := 25 ns;
prop_delay : time := 1 ns);
port(signal
signal
signal
signal
signal
signal
signal
signal
signal
CLK : out vlbit;
REG_DEST : out vlbit_1d(4 downto 0);
NEW_ROB : out vlbit_1d(3 downto 0);
ISSUE : out vlbit;
ROB_TO_COMMIT: out vlbit_1d(3 downto 0);
COMMIT : out vlbit;
REG_SOURCE : out vlbit_1d(4 downto 0);
ROB_OUT : in vlbit_1d(3 downto 0);
VALID : in vlbit);
end source2rob_tester;
architecture behavior of source2rob_tester is
-- Function definition of str2vec()
function str2vec(str: string; hi: integer; lo: integer) return vlbit_1d is
variable vtmp: vlbit_1d((hi-lo) downto 0);
variable index: integer;
begin
for i in lo to hi loop--str'range loop
index := i - lo;
if(str(i) = '1') then
vtmp(index) := '1';
elsif(str(i) = '0') then
vtmp(index) := '0';
else
vtmp(index) := 'X';
end if;
end loop;
return vtmp;
end;
function toString (str : string) return string is
begin
return str;
end;
begin
main: process
constant zero : vlbit_1d := "00000000000000000000000000000000";
variable file_line : line;
variable outputline : line;
file test_file : text is in "behv\source2rob_tester.txt";
variable str_in : string(32 downto 1);
variable reg_dest_in : vlbit_1d(4 downto 0);
variable new_rob_in : vlbit_1d(3 downto 0);
variable issue_in : vlbit;
variable rob_to_commit_in : vlbit_1d(3 downto 0);
variable commit_in : vlbit;
variable reg_source_in : vlbit_1d(4 downto 0);
variable rob_out_in : vlbit_1d(3 downto 0);
variable valid_in : vlbit;
variable error_num : integer;
begin
error_num := 0;
while not endfile(test_file) loop
readline(test_file, file_line);
read(file_line, str_in);
reg_dest_in := str2vec(str_in, 32, 28);
new_rob_in := str2vec(str_in, 26, 23);
issue_in := int2vlb(v1d2int(str2vec(str_in, 21, 21)));
rob_to_commit_in := str2vec(str_in, 19, 16);
commit_in := int2vlb(v1d2int(str2vec(str_in, 14, 14)));
reg_source_in := str2vec(str_in, 12, 8);
rob_out_in := str2vec(str_in, 6, 3);
valid_in := int2vlb(v1d2int(str2vec(str_in, 1, 1)));
REG_DEST <= reg_dest_in after prop_delay;
NEW_ROB <= new_rob_in after prop_delay;
ISSUE <= issue_in after prop_delay;
ROB_TO_COMMIT <= rob_to_commit_in after prop_delay;
COMMIT <= commit_in after prop_delay;
REG_SOURCE <= reg_source_in after prop_delay;
CLK <= '0';
wait for delay;
CLK <= '1';
wait for delay;
if ROB_OUT /= rob_out_in or VALID /= valid_in then
write(outputline, toString("ROB or VALID does not agree: "));
write(outputline, toString("ROB->"));
write(outputline, v1d2int(ROB_OUT));
write(outputline, toString(" ?= "));
write(outputline, v1d2int(rob_out_in));
write(outputline, toString(", VALID->"));
write(outputline, vlb2int(VALID));
write(outputline, toString(" ?= "));
write(outputline, vlb2int(valid_in));
error_num := error_num + 1;
else
write(outputline, toString("ROB and VALID agrees: "));
write(outputline, toString("ROB->"));
write(outputline, v1d2int(ROB_OUT));
write(outputline, toString(" = "));
write(outputline, v1d2int(rob_out_in));
write(outputline, toString(", VALID->"));
write(outputline, vlb2int(VALID));
write(outputline, toString(" = "));
write(outputline, vlb2int(valid_in));
end if;
writeline(output, outputline);
end loop;
write(outputline,
write(outputline,
write(outputline,
writeline(output,
wait;
end process main;
toString("Test ended with "));
error_num);
toString(" errors."));
outputline);
end behavior;
Appendix IV – Testing
4-bit mod adder
clock clk 0 1
vector in in[3:0]
vector out out[3:0]
wave 4BMaddtest.wfm clk in out
assign in 0\h
cycle
assign in 1\h
cycle
assign in 2\h
cycle
assign in 3\h
cycle
assign in 4\h
cycle
assign in 5\h
cycle
assign in 6\h
cycle
assign in 7\h
cycle
assign in 8\h
cycle
assign in 9\h
cycle
assign in A\h
cycle
assign in B\h
cycle
assign in C\h
cycle
assign in D\h
cycle
assign in E\h
cycle
assign in F\h
cycle
Branch Prediction testbench
------------------------------------------------------------------- VHDL Model of Branch Predictor Testbench
-----------------------------------------------------------------library pack1076;
use pack1076.pack1076.all;
library ieee;
use std.textio.all;
entity bpred_testbench is
port(signal PC : out vlbit_1d(31 downto 0);
signal INSTR : out vlbit_1d(31 downto 0);
signal UPDATE_ADDR: out vlbit_1d(31 downto 0);
signal RESET : out vlbit;
signal BRANCH_VALID : out vlbit;
signal PRED_VALIDATE : out vlbit;
signal CLK : in vlbit;
signal NEW_BRANCH_ADDR : in vlbit_1d(31 downto 0);
signal UNTAKEN_ADDR : in vlbit_1d(31 downto 0);
signal BRANCH : in vlbit);
end bpred_testbench;
architecture behavior of bpred_testbench is
function toString(dumb: string) return string is
begin
return dumb;
end;
function vlb2str(bit_in : vlbit) return string is
variable stmp: string(1 downto 1);
begin
if(bit_in = '1') then
stmp(1) := '1';
elsif(bit_in = '0') then
stmp(1) := '0';
else
stmp(1) := 'X';
end if;
return stmp;
end;
function vec32tohex(vec: vlbit_1d) return string is
variable str: string(10 downto 1);
variable lo: integer;
variable hi: integer;
begin
for i in 1 to 8 loop
lo := (i-1)*4;
hi := ((i-1)*4)+3;
if(vec(hi downto lo) = "0000") then
str(i) := '0';
elsif(vec(hi downto lo) = "0001") then
str(i) := '1';
elsif(vec(hi downto lo) = "0010") then
str(i) := '2';
elsif(vec(hi downto lo) = "0011") then
str(i) := '3';
elsif(vec(hi downto lo) = "0100") then
str(i) := '4';
elsif(vec(hi downto lo) = "0101") then
str(i) := '5';
elsif(vec(hi downto lo) = "0110") then
str(i) := '6';
elsif(vec(hi downto lo) = "0111") then
str(i) := '7';
elsif(vec(hi downto lo) = "1000") then
str(i) := '8';
elsif(vec(hi downto lo) = "1001") then
str(i) := '9';
elsif(vec(hi downto lo) = "1010") then
str(i) := 'A';
elsif(vec(hi downto lo) = "1011") then
str(i) := 'B';
elsif(vec(hi downto lo) = "1100") then
str(i) := 'C';
elsif(vec(hi downto lo) = "1101") then
str(i) := 'D';
elsif(vec(hi downto lo) = "1110") then
str(i) := 'E';
elsif(vec(hi downto lo) = "1111") then
str(i) := 'F';
else
str(i) := 'X';
end if;
end loop;
str(9) := 'x';
str(10) := '0';
return str;
end;
-- Function definition of vec2str()
function vec2str(vec: vlbit_1d) return string is
variable stmp: string(vec'left+1 downto 1);
begin
for i in vec'reverse_range loop
if(vec(i) = '1') then
stmp(i+1) := '1';
elsif(vec(i) = '0') then
stmp(i+1) := '0';
else
stmp(i+1) := 'X';
end if;
end loop;
return stmp;
end;
-- Function definition of str2vec()
function str2vec(str: string; hi: integer; lo: integer) return vlbit_1d is
variable vtmp: vlbit_1d((hi-lo) downto 0);
begin
for i in lo to hi loop--str'range loop
if(str(i) = '1') then
vtmp(i-lo) := '1';
elsif(str(i) = '0') then
vtmp(i-lo) := '0';
else
vtmp(i-lo) := 'X';
end if;
end loop;
return vtmp;
end;
-- Function definition of hexstr2vec()
function hexstr2vec(str: string; hi: integer; lo: integer) return vlbit_1d is
variable vtmp: vlbit_1d((hi-lo+1)*4-1 downto 0);
variable index: integer;
begin
for i in lo to hi loop
index := i - lo + 1;
if(str(i) = '0') then
vtmp(index*4 -1 downto (index-1)*4) := "0000";
elsif(str(i) = '1') then
vtmp(index*4 -1 downto (index-1)*4) := "0001";
elsif(str(i) = '2') then
vtmp(index*4 -1 downto (index-1)*4) := "0010";
elsif(str(i) = '3') then
vtmp(index*4 -1 downto (index-1)*4) := "0011";
elsif(str(i) = '4') then
vtmp(index*4 -1 downto (index-1)*4) := "0100";
elsif(str(i) = '5') then
vtmp(index*4 -1 downto (index-1)*4) := "0101";
elsif(str(i) = '6') then
vtmp(index*4 -1 downto (index-1)*4) := "0110";
elsif(str(i) = '7') then
vtmp(index*4 -1 downto (index-1)*4) := "0111";
elsif(str(i) = '8') then
vtmp(index*4 -1 downto (index-1)*4) := "1000";
elsif(str(i) = '9') then
vtmp(index*4 -1 downto (index-1)*4) := "1001";
elsif(str(i) = 'A') then
vtmp(index*4 -1 downto (index-1)*4) := "1010";
elsif(str(i) = 'B') then
vtmp(index*4 -1 downto (index-1)*4) := "1011";
elsif(str(i) = 'C') then
vtmp(index*4 -1 downto (index-1)*4) := "1100";
elsif(str(i) = 'D') then
vtmp(index*4 -1 downto (index-1)*4) := "1101";
elsif(str(i) = 'E') then
vtmp(index*4 -1 downto (index-1)*4) := "1110";
elsif(str(i) = 'F') then
vtmp(index*4 -1 downto (index-1)*4) := "1111";
end if;
end loop;
return vtmp;
end;
begin
-- This process applies stimulus to the design inputs, then it waits
-- for some amount of time so we can observe the results during simulation
stimulus:process
file test_file: text is in "behv\bptest.txt";
variable output_line : line;
variable file_line: line;
variable str_in: string(58 downto 1);
variable pc_i: vlbit_1d(31 downto 0);
variable instr_i: vlbit_1d(31 downto 0);
variable update_addr_i: vlbit_1d(31 downto 0);
variable pred_validate_i: vlbit_1d(0 downto 0);
variable branch_valid_i: vlbit_1d(0 downto 0);
variable branch_e: vlbit_1d(0 downto 0);
variable new_branch_addr_e: vlbit_1d(31 downto 0);
variable untaken_addr_e: vlbit_1d(31 downto 0);
variable name: string(8 downto 1);
variable error_num: integer;
begin
error_num := 0;
-- Hack to skip 2 comment lines
--# Must be tab separated, except line number
--#linenum, PC, INSTR, UPDATEAD, pval, bval, Exp Out
RESET <= '1';
PRED_VALIDATE <= '0';
wait until pfalling(clk);
wait for 20 ns;
RESET <= '0';
while not endfile(test_file) loop
wait until pfalling(clk);
wait for 20 ns;
readline(test_file, file_line);
read(file_line, str_in);
-- See bpred_test.txt for file layout
name := str_in(58 downto 51);
pc_i := hexstr2vec(str_in, 50, 43);
instr_i := hexstr2vec(str_in, 41, 34);
update_addr_i := hexstr2vec(str_in, 32, 25);
pred_validate_i := str2vec(str_in, 23, 23);
branch_valid_i := str2vec(str_in, 21, 21);
branch_e := str2vec(str_in, 19, 19);
new_branch_addr_e := hexstr2vec(str_in, 17, 10);
untaken_addr_e := hexstr2vec(str_in, 8, 1);
-- END bpred_test.txt parsing
PC <= pc_i;
INSTR <= instr_i;
UPDATE_ADDR <= update_addr_i;
PRED_VALIDATE <= pred_validate_i(0);
BRANCH_VALID <= branch_valid_i(0);
wait for 20 ns;
write(output_line, toString("** Test: "));
write(output_line, name);
writeline(output, output_line);
write(output_line, toString("** Input PC: "));
write(output_line, vec32tohex(pc_i));
writeline(output, output_line);
write(output_line, toString("** Input INSTR: "));
write(output_line, vec32tohex(instr_i));
writeline(output, output_line);
write(output_line, toString("** Input UPDATE_ADDR: "));
write(output_line, vec32tohex(update_addr_i));
writeline(output, output_line);
write(output_line, toString("** Input PRED_VALIDATE: "));
write(output_line, vec2str(pred_validate_i));
writeline(output, output_line);
write(output_line, toString("** Input BRANCH_VALID: "));
write(output_line, vec2str(branch_valid_i));
writeline(output, output_line);
write(output_line, toString("** Expected BRANCH: "));
write(output_line, vec2str(branch_e));
writeline(output, output_line);
write(output_line, toString("** Actual BRANCH:
write(output_line, vlb2str(BRANCH));
writeline(output, output_line);
"));
write(output_line, toString("** Expected NEW_BRANCH_ADDR: "));
write(output_line, vec32tohex(new_branch_addr_e));
writeline(output, output_line);
write(output_line, toString("** Actual NEW_BRANCH_ADDR: "));
write(output_line, vec32tohex(NEW_BRANCH_ADDR));
writeline(output, output_line);
write(output_line, toString("** Expected UNTAKEN_ADDR: "));
write(output_line, vec32tohex(untaken_addr_e));
writeline(output, output_line);
write(output_line, toString("** Actual UNTAKEN_ADDR: "));
write(output_line, vec32tohex(UNTAKEN_ADDR));
writeline(output, output_line);
if (branch_e /= int2v1d(vlb2int(BRANCH))(0 downto 0)) or
(new_branch_addr_e /= NEW_BRANCH_ADDR) or
(untaken_addr_e /= UNTAKEN_ADDR) then
assert false
report
"!!ERROR in testcase!!" & lf
severity error;
error_num := error_num + 1;
end if;
end loop;
if (error_num = 0) then
assert false
report
lf & "** All test passed"
severity note;
end if;
wait;
end process;
end behavior;
Branch Prediction testbench2
------------------------------------------------------------------- VHDL Model of Branch Predictor Testbench
-----------------------------------------------------------------library pack1076;
use pack1076.pack1076.all;
library ieee;
use std.textio.all;
entity bpred_testbench is
end bpred_testbench;
architecture behavior of bpred_testbench is
component branch_pred
port(PC, INSTR, UPDATE_ADDR:
CLK, RESET, BRANCH_VALID, PRED_VALIDATE:
TAKEN, BRANCH_INSTR:
BRANCH:
end component;
in vlbit_1d(31 downto 0);
in vlbit;
out vlbit;
out vlbit);
signal PC, INSTR, UPDATE_ADDR: vlbit_1d(31 downto 0);
signal TAKEN, BRANCH_INSTR: vlbit;
signal BRANCH_VALID, PRED_VALIDATE, BRANCH, CLK, RESET: vlbit;
function toString(dumb: string) return string is
begin
return dumb;
end;
function vlb2str(bit_in : vlbit) return string is
variable stmp: string(1 downto 1);
begin
if(bit_in = '1') then
stmp(1) := '1';
elsif(bit_in = '0') then
stmp(1) := '0';
else
stmp(1) := 'X';
end if;
return stmp;
end;
function vec32tohex(vec: vlbit_1d) return string is
variable str: string(10 downto 1);
variable lo: integer;
variable hi: integer;
begin
for i in 1 to 8 loop
lo := (i-1)*4;
hi := ((i-1)*4)+3;
if(vec(hi downto lo) = "0000") then
str(i) := '0';
elsif(vec(hi downto lo) = "0001") then
str(i) := '1';
elsif(vec(hi downto lo) = "0010") then
str(i) := '2';
elsif(vec(hi downto lo) = "0011") then
str(i) := '3';
elsif(vec(hi downto lo) = "0100") then
str(i) := '4';
elsif(vec(hi downto lo) = "0101") then
str(i) := '5';
elsif(vec(hi downto lo) = "0110") then
str(i) := '6';
elsif(vec(hi downto lo) = "0111") then
str(i) := '7';
elsif(vec(hi downto lo) = "1000") then
str(i) := '8';
elsif(vec(hi downto lo) = "1001") then
str(i) := '9';
elsif(vec(hi downto lo) = "1010") then
str(i) := 'A';
elsif(vec(hi downto lo) = "1011") then
str(i) := 'B';
elsif(vec(hi downto lo) = "1100") then
str(i) := 'C';
elsif(vec(hi downto lo) = "1101") then
str(i) := 'D';
elsif(vec(hi downto lo) = "1110") then
str(i) := 'E';
elsif(vec(hi downto lo) = "1111") then
str(i) := 'F';
else
str(i) := 'X';
end if;
end loop;
str(9) := 'x';
str(10) := '0';
return str;
end;
-- Function definition of vec2str()
function vec2str(vec: vlbit_1d) return string is
variable stmp: string(vec'left+1 downto 1);
begin
for i in vec'reverse_range loop
if(vec(i) = '1') then
stmp(i+1) := '1';
elsif(vec(i) = '0') then
stmp(i+1) := '0';
else
stmp(i+1) := 'X';
end if;
end loop;
return stmp;
end;
-- Function definition of str2vec()
function str2vec(str: string; hi: integer; lo: integer) return vlbit_1d is
variable vtmp: vlbit_1d((hi-lo) downto 0);
begin
for i in lo to hi loop--str'range loop
if(str(i) = '1') then
vtmp(i-lo) := '1';
elsif(str(i) = '0') then
vtmp(i-lo) := '0';
else
vtmp(i-lo) := 'X';
end if;
end loop;
return vtmp;
end;
-- Function definition of hexstr2vec()
function hexstr2vec(str: string; hi: integer; lo: integer) return vlbit_1d is
variable vtmp: vlbit_1d((hi-lo+1)*4-1 downto 0);
variable index: integer;
begin
for i in lo to hi loop
index := i - lo + 1;
if(str(i) = '0') then
vtmp(index*4 -1 downto (index-1)*4) := "0000";
elsif(str(i) = '1') then
vtmp(index*4 -1 downto (index-1)*4) := "0001";
elsif(str(i) = '2') then
vtmp(index*4 -1 downto (index-1)*4) := "0010";
elsif(str(i) = '3') then
vtmp(index*4 -1 downto (index-1)*4) := "0011";
elsif(str(i) = '4') then
vtmp(index*4 -1 downto (index-1)*4) := "0100";
elsif(str(i) = '5') then
vtmp(index*4 -1 downto (index-1)*4) := "0101";
elsif(str(i) = '6') then
vtmp(index*4 -1 downto (index-1)*4) := "0110";
elsif(str(i) = '7') then
vtmp(index*4 -1 downto (index-1)*4) := "0111";
elsif(str(i) = '8') then
vtmp(index*4 -1 downto (index-1)*4) := "1000";
elsif(str(i) = '9') then
vtmp(index*4 -1 downto (index-1)*4) := "1001";
elsif(str(i) = 'A') then
vtmp(index*4 -1 downto
elsif(str(i) = 'B') then
vtmp(index*4 -1 downto
elsif(str(i) = 'C') then
vtmp(index*4 -1 downto
elsif(str(i) = 'D') then
vtmp(index*4 -1 downto
elsif(str(i) = 'E') then
vtmp(index*4 -1 downto
elsif(str(i) = 'F') then
vtmp(index*4 -1 downto
end if;
end loop;
return vtmp;
(index-1)*4) := "1010";
(index-1)*4) := "1011";
(index-1)*4) := "1100";
(index-1)*4) := "1101";
(index-1)*4) := "1110";
(index-1)*4) := "1111";
end;
begin
-- Instantiate a Device Under Test (DUT) and map its I/O to the top
-- level signals
DUT: branch_pred port map (PC, INSTR, UPDATE_ADDR, CLK, RESET, BRANCH_VALID,
PRED_VALIDATE, TAKEN, BRANCH_INSTR, BRANCH);
-- This process applies stimulus to the design inputs, then it waits
-- for some amount of time so we can observe the results during simulation
stimulus:process
file test_file: text is in "behv\bpredtest2.txt";
variable output_line : line;
variable file_line: line;
variable str_in: string(40 downto 1);
variable pc_i: vlbit_1d(31 downto 0);
variable instr_i: vlbit_1d(31 downto 0);
variable update_addr_i: vlbit_1d(31 downto 0);
variable pred_validate_i: vlbit_1d(0 downto 0);
variable branch_valid_i: vlbit_1d(0 downto 0);
variable branch_e: vlbit_1d(0 downto 0);
variable name: string(8 downto 1);
variable error_num: integer;
begin
error_num := 0;
-- Hack to skip 2 comment lines
--# Must be tab separated, except line number
--#linenum, PC, INSTR, UPDATEAD, pval, bval, Exp Out
RESET <= '1';
PRED_VALIDATE <= '0';
wait until pfalling(clk);
wait for 5 ns;
RESET <= '0';
while not endfile(test_file) loop
wait until pfalling(clk);
wait for 5 ns;
readline(test_file, file_line);
read(file_line, str_in);
-- See bpred_test.txt for file layout
name := str_in(40 downto 33);
pc_i := hexstr2vec(str_in, 32, 25);
instr_i := hexstr2vec(str_in, 23, 16);
update_addr_i := hexstr2vec(str_in, 14, 7);
pred_validate_i := str2vec(str_in, 5, 5);
branch_valid_i := str2vec(str_in, 3, 3);
branch_e := str2vec(str_in, 1, 1);
-- END bpred_test.txt parsing
PC <= pc_i;
INSTR <= instr_i;
UPDATE_ADDR <= update_addr_i;
PRED_VALIDATE <= pred_validate_i(0);
BRANCH_VALID <= branch_valid_i(0);
wait for 5 ns;
write(output_line, toString("** Test: "));
write(output_line, name);
writeline(output, output_line);
write(output_line, toString("** Input PC: "));
write(output_line, vec32tohex(pc_i));
writeline(output, output_line);
write(output_line, toString("** Input INSTR: "));
write(output_line, vec32tohex(instr_i));
writeline(output, output_line);
write(output_line, toString("** Input UPDATE_ADDR: "));
write(output_line, vec32tohex(update_addr_i));
writeline(output, output_line);
write(output_line, toString("** Input PRED_VALIDATE: "));
write(output_line, vec2str(pred_validate_i));
writeline(output, output_line);
write(output_line, toString("** Input BRANCH_VALID: "));
write(output_line, vec2str(branch_valid_i));
writeline(output, output_line);
write(output_line, toString("** Expected BRANCH: "));
write(output_line, vec2str(branch_e));
writeline(output, output_line);
write(output_line, toString("** Actual BRANCH:
write(output_line, vlb2str(BRANCH));
writeline(output, output_line);
"));
if (branch_e /= int2v1d(vlb2int(BRANCH))(0 downto 0)) then
assert false
report
"!!ERROR in testcase!!" & lf
severity error;
error_num := error_num + 1;
end if;
end loop;
if (error_num = 0) then
assert false
report
lf & "** All test passed"
severity note;
end if;
wait;
end process;
end behavior;
Cache command file
stepsize 24ns
loadm foolio\odd\dram < test_files\seq.mem
loadm foolio\even\dram < test_files\seq.mem
vector
vector
vector
vector
vector
vector
vector
vector
vector
data_in data_in[31:0]
data_out data_out[31:0]
address address[9:0]
am address_to_mem[8:0]
data_in_to_mem data_in_to_mem[63:0]
do do[63:0]
odd_address foolio\a_oo[4:0]
even_address foolio\a_oe[4:0]
data_even foolio\D_IOE[31:0]
vector data_odd foolio\D_IOO[31:0]
vector phoebus_is_a_fool foolio\data_out[63:0]
vector
vector
vector
vector
vector
vector
vector
vector
vector
vector
vector
vector
vector
vector
vector
vector
vector
vector
vector
vector
vector
vector
vector
vector
vector
tag0 koichi\tag_out0[8:0]
tag1 koichi\tag_out1[8:0]
tag2 koichi\tag_out2[8:0]
tag3 koichi\tag_out3[8:0]
tag4 koichi\tag_out4[8:0]
tag5 koichi\tag_out5[8:0]
tag6 koichi\tag_out6[8:0]
tag7 koichi\tag_out7[8:0]
victim koichi\victim[2:0]
zero_zero koichi\block0_word0[31:0]
zero_one koichi\block0_word1[31:0]
one_zero koichi\block1_word0[31:0]
one_one koichi\block1_word1[31:0]
two_zero koichi\block2_word0[31:0]
two_one koichi\block2_word1[31:0]
three_zero koichi\block3_word0[31:0]
three_one koichi\block3_word1[31:0]
four_zero koichi\block4_word0[31:0]
four_one koichi\block4_word1[31:0]
five_zero koichi\block5_word0[31:0]
five_one koichi\block5_word1[31:0]
six_zero koichi\block6_word0[31:0]
six_one koichi\block6_word1[31:0]
seven_zero koichi\block7_word0[31:0]
seven_one koichi\block7_word1[31:0]
wave cachetest_v2.wfm clk reset address data_in am data_in_to_mem do data_out read write
pipeline_stall request r_w wait even_address data_even odd_address data_odd foolio\RAS_L
foolio\CAS_L foolio\OE_L foolio\WE_L tag0 tag1 tag2 tag3 tag4 tag5 tag6 tag7 victim
zero_zero zero_one one_zero one_one two_zero two_one three_zero three_one four_zero
four_one five_zero five_one six_zero six_one seven_zero seven_one phoebus_is_a_fool
In Out test
library pack1076;
use pack1076.pack1076.all;
use std.textio.all;
entity inout_test is
generic (
delay : time := 6 ns);
port (
--Interface to Pipeline
signal clk : in vlbit;
signal r_w : in vlbit;
--1 when processor is doing a write
signal d_ioo : inout vlbit_1d(31 downto 0);
signal d_ioe : inout vlbit_1d(31 downto 0);
signal d64out : out vlbit_1d(63 downto 0));
end inout_test;
architecture behavior of inout_test is
function toString(dumb: string) return string is
begin
return dumb;
end;
function vec32tohex(vec: vlbit_1d; inlo:integer) return string is
variable str: string(8 downto 1);
variable lo: integer;
variable hi: integer;
begin
for i in 1 to 8 loop
lo := inlo+(i-1)*4;
hi := inlo+((i-1)*4)+3;
if(vec(hi downto lo) = "0000") then
str(i) := '0';
elsif(vec(hi downto lo) = "0001")
str(i) := '1';
elsif(vec(hi downto lo) = "0010")
str(i) := '2';
elsif(vec(hi downto lo) = "0011")
str(i) := '3';
elsif(vec(hi downto lo) = "0100")
str(i) := '4';
elsif(vec(hi downto lo) = "0101")
str(i) := '5';
elsif(vec(hi downto lo) = "0110")
str(i) := '6';
elsif(vec(hi downto lo) = "0111")
str(i) := '7';
elsif(vec(hi downto lo) = "1000")
str(i) := '8';
elsif(vec(hi downto lo) = "1001")
str(i) := '9';
elsif(vec(hi downto lo) = "1010")
str(i) := 'A';
elsif(vec(hi downto lo) = "1011")
str(i) := 'B';
elsif(vec(hi downto lo) = "1100")
str(i) := 'C';
elsif(vec(hi downto lo) = "1101")
str(i) := 'D';
elsif(vec(hi downto lo) = "1110")
str(i) := 'E';
elsif(vec(hi downto lo) = "1111")
str(i) := 'F';
elsif((vec(hi downto hi) = "X")
or (vec(hi-1 downto hi-1) =
or (vec(hi-2 downto hi-2) =
or (vec(hi-3 downto hi-3) =
str(i) := 'X';
else
str(i) := 'Z';
end if;
end loop;
return str;
end;
begin
then
then
then
then
then
then
then
then
then
then
then
then
then
then
then
"X")
"X")
"X")) then
-- behavior
inout_test: process
variable d64in : vlbit_1d(63 downto 0);
begin
wait until pfalling(clk);
if r_w = '1' then
wait for 5 ns;
d_ioo <= "11111111111111111111111111111111";
d_ioe <= "01010101010101010101010101010101";
wait for 5 ns;
else
wait for 5 ns;
d64in(63 downto 32) := d_ioo;
d64in(31 downto 0) := d_ioe;
d64out <= d64in after delay;
wait for 5 ns;
end if;
d_ioo <= "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ";
d_ioe <= "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ";
wait for 5 ns;
end process;
end behavior;
JR Unit command file
stepsize 50ns
clock clk 0 1
vector
vector
vector
vector
ROB_IN ROB_IN[3:0]
CDB CDB[35:0]
JR_PC JR_PC[31:0]
REG_OUT REG_OUT[31:0]
wave jr_unit_test.vwf CLK ISSUE_JR VALUE_READY REG_OUT ROB_IN SQUISH JR_CAN_WRITE
~CDB_WRITE_VALUE CDB ENABLE_JR_PC JR_PC
l ISSUE_JR VALUE_READY ROB_IN SQUISH JR_CAN_WRITE CDB REG_OUT
h ~CDB_WRITE_VALUE
c 10
| first check the case where it's going to do a JR and the value is ready immediately
(i.e., the value is in the register or the ROB)
sim 10ns
h ISSUE_JR
h VALUE_READY
assign REG_OUT a55face\h
|case if JR_CAN_WRITE is high
h JR_CAN_WRITE
c
assign REG_OUT f00\h
|case if JR_CAN_WRITE is low
l JR_CAN_WRITE
c
l ISSUE_JR
c 3
h JR_CAN_WRITE
c
l JR_CAN_WRITE
| now check if the value is not ready, and it comes from the CDB.
h ISSUE_JR
l VALUE_READY
assign ROB_IN c\h
c
l ISSUE_JR
c
c
assign CDB cffffffff\h
l ~CDB_WRITE_VALUE
| case if JR_CAN_WRITE is high
h JR_CAN_WRITE
c
h ~CDB_WRITE_VALUE
l JR_CAN_WRITE
c 4
h ISSUE_JR
assign ROB_IN b\h
c
l ISSUE_JR
c 3
l ~CDB_WRITE_VALUE | wrong value
c
assign CDB bffff0000\h
| case if JR_CAN_WRITE is low
l JR_CAN_WRITE
c
h ~CDB_WRITE_VALUE
c 3
h JR_CAN_WRITE
c
l JR_CAN_WRITE
c 4
| Squish version
h ISSUE_JR
h VALUE_READY
h SQUISH
assign REG_OUT a55face\h
|case if JR_CAN_WRITE is high
h JR_CAN_WRITE
c
l SQUISH
assign REG_OUT f00\h
|case if JR_CAN_WRITE is low
l JR_CAN_WRITE
c
l ISSUE_JR
c
h SQUISH
c 3
| now check if the value is not ready, and it comes from the CDB.
h ISSUE_JR
l VALUE_READY
assign ROB_IN c\h
c
l ISSUE_JR
c
h SQUISH
c
l SQUISH
assign CDB cffffffff\h
l ~CDB_WRITE_VALUE
c
h ~CDB_WRITE_VALUE
c 4
h ISSUE_JR
assign ROB_IN b\h
c
l ISSUE_JR
c 3
l ~CDB_WRITE_VALUE | wrong value
c
assign CDB bffff0000\h
| case if JR_CAN_WRITE is low
h SQUISH
c
h ~CDB_WRITE_VALUE
c 3
c
c 4
Op Queue command file
stepsize 50ns
clock clk 0 1
vector
vector
vector
vector
vector
vector
vector
vector
vector
din din[31:0]
dout dout[31:0]
pcin pcin[31:0]
mri mri[31:0]
br_in br_in[31:0]
pcout pcout[31:0]
br_out br_out[31:0]
head op\head[4:0]
tail op\tail[4:0]
wave opQtest.wfm clk din pcin br_in predict_in squash insert send dout pcout br_out
predict_out full empty head tail mri
l din pcin br_in predict_in
l send squash insert
c 5
h din0 pcin0 br_in0 predict_in
|sim 25ns
h insert
c
l insert
c 5
l
h
c
l
c
din0 pcin0 br_in0
din1 insert pcin1 br_in1
insert
5
h send
c
l send
c 5
h din0 insert pcin0 br_in0
c
l insert
c 5
l
h
c
l
c
din0 din1 pcin0 pcin1 br_in0 br_in1
din2 insert pcin2 br_in2
insert
5
h din0 insert pcin0 br_in0
c
l insert
c 5
l
h
c
l
c
din0 pcin0 br_in0
din1 insert pcin1 br_in1
insert
5
h din0 insert pcin0 br_in0
c
l insert
c 5
l
h
c
l
c
din0 din1 din2 pcin0 pcin1 pcin2 br_in0 br_in1 br_in2
din3 insert pcin3 br_in3
insert
5
h din0 insert pcin0 br_in0
c
l insert
c 5
l
h
c
l
c
din0 pcin0 br_in0
din1 insert pcin1 br_in1
insert
5
h din0 insert pcin0 br_in0
c
l insert
c 5
l
h
c
l
c
din0 din1 pcin0 pcin1 br_in0 br_in1
din2 insert pcin2 br_in2
insert
5
h din0 insert pcin0 br_in0
c
l insert
c 5
l
h
c
l
c
din0 pcin0 br_in0
din1 insert pcin1 br_in1
insert
5
h din0 insert pcin0 br_in0
c
l insert
c 5
l
h
c
l
c
din0 din1 din2 din3 pcin0 pcin1 pcin2 pcin3 br_in0 br_in1 br_in2 br_in3
din4 insert pcin4 br_in4
insert
5
h send
c
l send
c 5
h din0 insert pcin0 br_in0
c
l insert
c 5
h send
c
l send
c 5
Reservation Station Squish command file
stepsize 30ns
|clock clk 1 0
clock clk 0 1
vector nr nr[15:0]
vector fuinsel fuinsel[3:0]
vector listen listen[3:0]
vector issue issue[84:0]
vector aluina aluina[31:0]
vector aluinb aluinb[31:0]
vector aluout aluout[31:0]
vector cdb cdb[37:0]
vector dout dout[31:0]
vector doutb doutb[31:0]
vector fakecdb fakecdb[37:0]
vector res res[3:0]
vector reset reset[15:0]
vector func func[8:0]
vector cdb_upper[3:0]
vector branch_rob_plus_two branch_rob_plus_two[3:0]
vector front front[3:0]
wave RStester.wfm clk is clk reset res full nr fuinsel listen issue aluina aluinb aluout
cdb dout doutb fakecdb launch grant func branch_rob_plus_two front squish sq broadcast
cdbreq
l is
sim 30ns |(half a cycle)
l grant
l squish
c 2
r aluina aluinb aluout reset grant
|First, try a few instructions that have all their arguments
h is
assign issue "1603111111112222222200\h"
c
|add 0x11111111 0x22222222 = 0x33333333
assign issue "0744ffffffff0000000100\h"
c
|slt 0xFFFFFFFF 0x00000001 = 0x00000001
|Now, try some instructions that require reservations to listen to the cdb, before
executing
assign issue "041577777777xxxxxxxxxa\h"
|Qk needs to wait for ROB 10
|and 0x77777777 0xcccccccc = 0x44444444
c
l is
assign cdb "0bdddddddd\h"
|wrong ROB - RS should ignore this
c
assign cdb "0acccccccc\h"
|right ROB - RS should take this
c
|Now issue an instruction WHILE another RS is waiting for its value
h is
assign issue "0236xxxxxxxx01234567fx\h"
|xor 0x11111111 0x01234567 = 0x10325476
|Qj needs to wait for ROB 15
c
assign issue "162766666666aaaaaaaaxx\h"
|or 0x66666666 0xaaaaaaaa = 0xeeeeeeee
c
l is
c 2
h is
assign issue "xe08ffffffff00000003xx\h"
assign cdb "0bcccccccc\h"
|add 0xffffffff 0x00000003 = 0x00000002
c
l is
assign branch_rob_plus_two "4\h"
assign front "9\h"
|h squish
|add 0xffffffff 0x00000003 = 0x00000002
c
l squish
h is
assign issue "x6c9ffffffff00000001xx\h"
|sltu 0xFFFFFFFF 0x00000001 = 0x00000000
assign cdb "0bcccccccc\h"
|wrong ROB - RS should ignore this
c
assign cdb "0f11111111\h"
|right ROB - RS should take this
l is
c 16
Reservation Station command file
stepsize 30ns
|clock clk 1 0
clock clk 0 1
vector nr nr[15:0]
vector fuinsel fuinsel[3:0]
vector listen listen[3:0]
vector issue issue[84:0]
vector aluina aluina[31:0]
vector aluinb aluinb[31:0]
vector aluout aluout[31:0]
vector cdb cdb[37:0]
vector dout dout[31:0]
vector doutb doutb[31:0]
vector fakecdb fakecdb[37:0]
vector res res[3:0]
vector reset reset[15:0]
vector func func[8:0]
vector cdb_upper[3:0]
wave RStester.wfm clk is clk reset res full nr fuinsel listen issue aluina aluinb aluout
cdb dout doutb fakecdb launch grant func
l is
h grant
sim 30ns |(half a cycle)
c
r grant
c
r aluina aluinb aluout reset
|First, try a few instructions that have all their arguments
h is
assign issue "1603111111112222222200\h"
c
|add 0x11111111 0x22222222 = 0x33333333
assign issue "0744ffffffff0000000100\h"
c
|slt 0xFFFFFFFF 0x00000001 = 0x00000001
|Now, try some instructions that require reservations to listen to the cdb, before
executing
assign issue "041577777777xxxxxxxxxa\h"
|Qk needs to wait for ROB 10
|and 0x77777777 0xcccccccc = 0x44444444
c
l is
assign cdb "0bdddddddd\h"
|wrong ROB - RS should ignore this
c
assign cdb "0acccccccc\h"
|right ROB - RS should take this
c
|Now issue an instruction WHILE another RS is waiting for its value
h is
assign issue "0236xxxxxxxx01234567fx\h"
|xor 0x11111111 0x01234567 = 0x10325476
|Qj needs to wait for ROB 15
c
assign issue "162766666666aaaaaaaaxx\h"
|or 0x66666666 0xaaaaaaaa = 0xeeeeeeee
c
l is
c 2
h is
assign issue "xe09ffffffff00000003xx\h"
assign cdb "0bcccccccc\h"
|add 0xffffffff 0x00000003 = 0x00000002
c
assign issue "x6c8ffffffff00000001xx\h"
|sltu 0xFFFFFFFF 0x00000001 = 0x00000000
assign cdb "0bcccccccc\h"
|wrong ROB - RS should ignore this
c
assign cdb "0f11111111\h"
|right ROB - RS should take this
l is
c 16
Source to ROB tester
------------------------------------------------- source2rob test bench version 3.1415926535897
-----------------------------------------------library pack1076;
use pack1076.pack1076.all;
library ieee;
use std.textio.all;
entity source2rob_tester is
generic (
delay
: time := 25 ns;
prop_delay : time := 1 ns);
port(signal
signal
signal
signal
signal
signal
signal
signal
signal
CLK : out vlbit;
REG_DEST : out vlbit_1d(4 downto 0);
NEW_ROB : out vlbit_1d(3 downto 0);
ISSUE : out vlbit;
ROB_TO_COMMIT: out vlbit_1d(3 downto 0);
COMMIT : out vlbit;
REG_SOURCE : out vlbit_1d(4 downto 0);
ROB_OUT : in vlbit_1d(3 downto 0);
VALID : in vlbit);
end source2rob_tester;
architecture behavior of source2rob_tester is
-- Function definition of str2vec()
function str2vec(str: string; hi: integer; lo: integer) return vlbit_1d is
variable vtmp: vlbit_1d((hi-lo) downto 0);
variable index: integer;
begin
for i in lo to hi loop--str'range loop
index := i - lo;
if(str(i) = '1') then
vtmp(index) := '1';
elsif(str(i) = '0') then
vtmp(index) := '0';
else
vtmp(index) := 'X';
end if;
end loop;
return vtmp;
end;
function toString (str : string) return string is
begin
return str;
end;
begin
main: process
constant zero : vlbit_1d := "00000000000000000000000000000000";
variable file_line : line;
variable outputline : line;
file test_file : text is in "behv\source2rob_tester.txt";
variable str_in : string(32 downto 1);
variable reg_dest_in : vlbit_1d(4 downto 0);
variable new_rob_in : vlbit_1d(3 downto 0);
variable issue_in : vlbit;
variable rob_to_commit_in : vlbit_1d(3 downto 0);
variable commit_in : vlbit;
variable reg_source_in : vlbit_1d(4 downto 0);
variable rob_out_in : vlbit_1d(3 downto 0);
variable valid_in : vlbit;
variable error_num : integer;
begin
error_num := 0;
while not endfile(test_file) loop
readline(test_file, file_line);
read(file_line, str_in);
reg_dest_in := str2vec(str_in, 32, 28);
new_rob_in := str2vec(str_in, 26, 23);
issue_in := int2vlb(v1d2int(str2vec(str_in, 21, 21)));
rob_to_commit_in := str2vec(str_in, 19, 16);
commit_in := int2vlb(v1d2int(str2vec(str_in, 14, 14)));
reg_source_in := str2vec(str_in, 12, 8);
rob_out_in := str2vec(str_in, 6, 3);
valid_in := int2vlb(v1d2int(str2vec(str_in, 1, 1)));
REG_DEST <= reg_dest_in after prop_delay;
NEW_ROB <= new_rob_in after prop_delay;
ISSUE <= issue_in after prop_delay;
ROB_TO_COMMIT <= rob_to_commit_in after prop_delay;
COMMIT <= commit_in after prop_delay;
REG_SOURCE <= reg_source_in after prop_delay;
CLK <= '0';
wait for delay;
CLK <= '1';
wait for delay;
if ROB_OUT /= rob_out_in or VALID /= valid_in then
write(outputline, toString("ROB or VALID does not agree: "));
write(outputline, toString("ROB->"));
write(outputline, v1d2int(ROB_OUT));
write(outputline, toString(" ?= "));
write(outputline, v1d2int(rob_out_in));
write(outputline, toString(", VALID->"));
write(outputline, vlb2int(VALID));
write(outputline, toString(" ?= "));
write(outputline, vlb2int(valid_in));
error_num := error_num + 1;
else
write(outputline, toString("ROB and VALID agrees: "));
write(outputline, toString("ROB->"));
write(outputline, v1d2int(ROB_OUT));
write(outputline, toString(" = "));
write(outputline, v1d2int(rob_out_in));
write(outputline, toString(", VALID->"));
write(outputline, vlb2int(VALID));
write(outputline, toString(" = "));
write(outputline, vlb2int(valid_in));
end if;
writeline(output, outputline);
end loop;
write(outputline,
write(outputline,
write(outputline,
writeline(output,
wait;
end process main;
end behavior;
toString("Test ended with "));
error_num);
toString(" errors."));
outputline);
Download